R:ddply重复每年累积数据

4

此问题相关,但出于清晰起见,我决定提出另一个问题。简而言之,我正在使用ddply来累加三年中每个值的总和。我的代码从第一年获取数据并在该列的第二年和第三年重复。我猜测每个1年块都被复制到整个列中,但我不知道为什么会这样。

问:如何在指定列的正确行中获取每年的累积和?

[编辑:for循环(或类似的东西)非常重要,因为最终我想通过列名列表自动计算新列,而不是手动计算每个新列。循环遍历列名列表。]

enter image description here

我经常使用ddply和cumsum组合,所以突然出现问题让我感到非常恼火。

[编辑:此代码已更新为我解决方案,该解决方案基于下面@Chase的答案]

require(lubridate)
require(plyr)
require(xts)
require(reshape)
require(reshape2)

set.seed(12345)
# create dummy time series data
monthsback <- 24
startdate <- as.Date(paste(year(now()),month(now()),"1",sep = "-")) - months(monthsback)
mydf <- data.frame(mydate = seq(as.Date(startdate), by = "month", length.out = monthsback),
                   myvalue1 = runif(monthsback, min = 600, max = 800),
                   myvalue2 = runif(monthsback, min = 1900, max = 2400),
                   myvalue3 = runif(monthsback, min = 50, max = 80),
                   myvalue4 = runif(monthsback, min = 200, max = 300))

mydf$year <- as.numeric(format(as.Date(mydf$mydate), format="%Y"))
mydf$month <- as.numeric(format(as.Date(mydf$mydate), format="%m"))

# Select columns to process
newcolnames <- c('myvalue1','myvalue4','myvalue2')

# melt n' cast
mydf.m <- mydf[,c('mydate','year',newcolnames)]
mydf.m <- melt(mydf.m, measure.vars = newcolnames)
mydf.m <- ddply(mydf.m, c("year", "variable"), transform, newcol = cumsum(value))
mydf.m <- dcast(mydate ~ variable, data = mydf.m, value.var = "newcol")
colnames(mydf.m) <- c('mydate',paste(newcolnames, "_cum", sep = ""))
mydf <- merge(mydf, mydf.m, by = 'mydate', all = FALSE)
mydf
1个回答

4

我并不是很理解你的for循环,但是你是否在过度复杂化问题?你能不能直接使用transformddply

#Make sure it's ordered properly
mydf <- mydf[order(mydf$year, mydf$month),]

#Use ddply to calculate the cumsum by year:
ddply(mydf, "year", transform, 
      cumsum1 = cumsum(myvalue1), 
      cumsum2 = cumsum(myvalue2))
#----------
       mydate myvalue1 myvalue2 year month   cumsum1   cumsum2
1  2010-05-01 744.1808 264.4543 2010     5  744.1808  264.4543
2  2010-06-01 775.1546 238.9828 2010     6 1519.3354  503.4371
3  2010-07-01 752.1965 269.8544 2010     7 2271.5319  773.2915
....
9  2011-01-01 745.5411 218.7712 2011     1  745.5411  218.7712
10 2011-02-01 797.9474 268.1834 2011     2 1543.4884  486.9546
11 2011-03-01 606.9071 237.0104 2011     3 2150.3955  723.9650
...
21 2012-01-01 690.7456 225.9681 2012     1  690.7456  225.9681
22 2012-02-01 665.3505 232.1225 2012     2 1356.0961  458.0906
23 2012-03-01 793.0831 206.0195 2012     3 2149.1792  664.1101

编辑 - 我没有在这台机器上安装R,所以这个内容未经测试,但这是我想到的:

require(reshape2)
mydf.m <- melt(mydf, measure.vars = newcolnames)
mydf.m <- ddply(mydf.m, c("year", "variable"), transform, newcol = cumsum(value))
dcast(mydate + year + month  ~ variable, data = mydf.m, value.var = "newcol")

谢谢@Chase。当我处理小的静态组,比如2-3列时,我可以直接(并成功地)使用ddplytransform。然而昨天我发现我需要对12个数据系列进行操作,这让我得出结论,我的当前方法直接编码每个值是不可扩展的,需要重新思考。for循环是我尝试自动化构建这些年度累计总数列(以及其他常见计算)的方法。 - SlowLearner
@SlowLearner - 明白了。我首先想到的是将您的数据“融化”成长格式,然后使用ddply在“年份”和“变量”上进行分组计算,最后再转换回宽格式。 - Chase
谢谢您的建议。我在概念上遇到了一些问题,我猜您的意思是放弃for循环... 我已经尝试过 mydf <- melt(mydf, id = c('mydate','year','month')) mydf$newcol <- 1 mydf <- ddply(mydf, .(year, variable), transform, newcol = cumsum(value)) colnames(mydf)[colnames(mydf)=="newcol"] <- paste(variable, "_cuml", sep = "", collapse = "") mydf <- cast(mydf, mydate ~ variable + newcol) 这个方法似乎可以解决问题,但我无法确定最终的转换以将newcol返回到宽格式。您能帮忙吗? - SlowLearner
@SlowLearner - 请看我的编辑。我现在不在R终端,但这就是我想要的! - Chase
谢谢,这确实创建了一个新的数据框,其中包含原始列的累积总和。我想我可以采用这种方法,重命名新列并将其合并到原始数据框中,所以这非常有帮助。在使用dcast时,是否有一种方法可以将新列附加到原始数据框,而不是用新计算的列替换原始列?(我已经查看了帮助文件,但没有看到明显的内容。) - SlowLearner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接