2012-05-10 41 views
4

与此问题相关here,但为了清晰起见,我决定再提一个问题,因为“新”问题与原始问题没有直接关系。简而言之,我使用ddply累计三年中每一年的价值。我的代码从第一年开始获取数据,并在第二年和第三年的行中重复使用。我的猜测是每个1年的块都被复制到整个列中,但我不明白为什么。R:ddply重复年度累计数据

问:我怎样才能得到指定列的右边每一年的累积和值?

[编辑:for循环 - 或类似的 - 很重要,因为最终我想根据列名称列表自动计算新列,而不是手动计算每个新列。该循环遍历列名的列表。]

enter image description here

我使用ddply和cumsum组合频繁,因此非常令人烦恼,一下子是具有与它的问题。

[编辑:此代码已被更新,以解决我看中了,这是基于以下@大通的答案]

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 

回答

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 

编辑 - 这是未经测试,因为我没有读该机器上,但是这是我脑子里想的:

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") 
+0

谢谢@Chase。当我处理一个小的静态组时,我可以并且确实直接(并且成功)使用'ddply'和'transform',比如说2-3列。然后,昨天我发现我需要为12个数据系列做这件事,这让我得出结论,我目前对每个数值进行直接编码的方法并没有扩展,需要重新考虑。 'for'循环是我试图自动完成这些每年运行总计(以及其他各种常见计算)的列的构建。 – SlowLearner

+0

@SlowLearner - gotcha。首先想到的是将数据“融化”为长格式,然后用'ddply'对'year'和'variable'进行分组,然后'cast'回到宽格式 – Chase

+0

感谢您的建议。我在概念化你的意思时遇到问题。我想你的意思是垃圾的'for'循环...我试过'mydf < - 熔化(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