【问题标题】:R: ddply repeats yearly cumulative dataR:ddply 重复年度累积数据
【发布时间】:2012-05-10 14:34:00
【问题描述】:

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

问。如何在指定列的右侧行中获得每年的累积总和值?

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

我经常使用 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

【问题讨论】:

    标签: r plyr


    【解决方案1】:

    我并没有真正遵循您的 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。当我处理一个小的静态组时,我可以并且确实直接(并且成功地)使用ddplytransform,比如 2-3 列。然后昨天我发现我需要为 12 个数据系列执行此操作,这让我得出结论,我目前直接编码每个值的方法无法扩展,需要重新考虑。 for 循环是我尝试自动构建包含这些年度运行总计(以及各种其他常见计算)的列。
    • @SlowLearner - 明白了。首先想到的是将melt 你的数据转换为长格式,然后用ddplyyearvariable 分组进行计算,然后将cast 重新转换为宽格式
    • 感谢您的建议。我在概念化你的意思时遇到问题。我猜你的意思是垃圾 for 循环......我已经尝试过 mydf &lt;- melt(mydf, id = c('mydate','year','month')) mydf$newcol &lt;- 1 mydf &lt;- ddply(mydf, .(year, variable), transform, newcol = cumsum(value)) colnames(mydf)[colnames(mydf)=="newcol"] &lt;- paste(variable, "_cuml", sep = "", collapse = "") mydf &lt;- cast(mydf, mydate ~ variable + newcol) 这似乎工作,除了我不能完全计算出最终的演员阵容让 newcol 回到宽格式。你愿意帮忙吗?
    • @SlowLearner - 查看我的编辑。我现在不在 R 终端,但这就是我的想法!
    • 谢谢,这确实创建了一个新的数据框,其中两列包含原始列的累积总和。我想我可以接受这个,重命名新列并将其合并到原始数据框中,所以这非常有帮助。在使用 dcast 将新列附加到原始数据框而不是用新计算的列替换原始列时,是否有办法? (我已经浏览了帮助文件,但看不到任何明显的东西。)
    猜你喜欢
    • 1970-01-01
    • 2019-02-04
    • 2017-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多