2012-05-10 67 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