【问题标题】:sum within (date)(日期)内的总和
【发布时间】:2013-03-12 20:33:31
【问题描述】:

我正在尝试计算同一日期出现的值的总和(XYZmin)。

我的数据是这样的,

bar <- structure(list(date = structure(c(15622, 15622, 15622, 15628, 
15632, 15635, 15639, 15639, 15639, 15639, 15639, 15642, 15646, 
15646, 15650, 15650, 15650, 15657, 15660, 15660, 15674, 15681, 
15691, 15695, 15709, 15716, 15723, 15730, 15737, 15737, 15737, 
15737, 15737, 15737, 15740, 15743, 15743, 15743, 15744, 15744, 
15744, 15744, 15746, 15751, 15755, 15758), class = "Date"), XYZmin = c(-20, 
-15, -10, -70, -60, -60, -95, -10, -10, -40, -25, -25, -20, -10, 
-3, -5, -25, -5, -70, -5, -30, -30, -25, 60, 60, 60, 60, 60, 
-10, -10, -30, -30, -10, -10, -10, -60, -30, -10, 75, -10, -10, 
-10, 60, 60, -15, 60)), .Names = c("date", "XYZmin"), class = "data.frame", row.names = c(NA, 
-46L))

head(bar)   
        date XYZmin
1 2012-10-09    -20
2 2012-10-09    -15
3 2012-10-09    -10
4 2012-10-15    -70
5 2012-10-19    -60
6 2012-10-22    -60

我正在努力完成的是创建一个新变量XYZtot,其中,在多次出现的数据中,对第二个数据的第一个和第二个值求和,并对第一个、第二个和第三个求和第三个数据的值。这是我的目标的一个片段。

head(new_bar_with_XYZtot) 

        date XYZmin XYZtot
1 2012-10-09    -20    -20
2 2012-10-09    -15    -35
3 2012-10-09    -10    -40
4 2012-10-15    -70    -70
5 2012-10-19    -60    -60
6 2012-10-22    -60    -60

更新了 big microbenchmark 测试

alexwhan <- function(bar,date,XYZmin) ddply(bar, .(date), transform, XYZmin.sum = cumsum(XYZmin))

Arun <- function(bar,date,XYZmin) within(bar, {XYZtot <- ave( XYZmin, date, FUN=cumsum)})

agstudy <- function(bar,date,XYZmin) transform(bar, XYZtot = ave(XYZmin, date, FUN = cumsum))

# install.packages("data.table", dependencies = TRUE)
library(data.table)
mnel <- function(bar,date,XYZmin)  bar <- data.table(bar); bar[, XYZmin.sum := cumsum(XYZmin), by = date]

# install.packages("microbenchmark", dependencies = TRUE)
require(microbenchmark)

# run test
res <- microbenchmark(alexwhan(bar,date,XYZmin), Arun(bar,date,XYZmin), agstudy(bar,date,XYZmin), mnel(bar,date,XYZmin), times = 666)


## Print results:
print(res)

数字,

Unit: microseconds
                        expr       min        lq    median        uq       max neval
 alexwhan(bar, date, XYZmin) 14484.077 15056.613 15237.760 15945.482 72650.126   666
     Arun(bar, date, XYZmin)   963.632  1018.311  1070.759  1138.655  4988.226   666
  agstudy(bar, date, XYZmin)  1967.292  2021.115  2078.261  2158.689  9240.500   666
     mnel(bar, date, XYZmin)   251.312   270.295   282.821   325.040  6540.367   666


### Plot results:
boxplot(res)

【问题讨论】:

    标签: r sum base


    【解决方案1】:

    如果您要花钱,我会提供data.table 解决方案

    library(data.table)
    bar <- data.table(bar)
    
    # assigning within bar
    bar[, XYZmin.sum := cumsum(XYZmin), by = date]
    

    这将适用于大数据!

    【讨论】:

    • 令人印象深刻。我将您的解决方案添加到 big microbenchmark 测试中。感谢您的回复。
    • 有没有一种简单的方法来设置所有值的总和NA,但不是总数?对于第一个日期 (2012-10-09),这将需要在 NA's' 中重新编码 -20-35。谢谢。
    【解决方案2】:

    也使用ave,但与transform一起使用

    transform(bar, XYZtot = ave(XYZmin, date, FUN = cumsum))
    

    EDIT在OP评论之后

    transform(bar, XYZtot = ave(XYZmin, date, FUN = 
                              function(x)
                                if(length(x) < 1) NA 
                                else c(cumsum(x[-length(x)]),NA)))
    

    【讨论】:

    • 删除了date之前的$符号。
    • 我最终使用了这个解决方案,它在微基准测试中也表现出色(见上文)。
    • 有没有一种简单的方法来设置所有值的总和NA,但不是总数?对于第一个日期 (2012-10-09),这将需要在 NA's' 中重新编码 -20-35
    【解决方案3】:

    这是一个使用ave的:

    bar <- within(bar, {XYZtot <- ave( XYZmin, date, FUN=cumsum)})
    

    【讨论】:

    • 更简洁,谢谢!我喜欢你如何使用within
    • 感谢@AnandaMahto! avewithinreshape 的领主 :)
    • 有没有一种简单的方法来设置所有值的总和NA,但不是总数?对于第一个日期 (2012-10-09),这将需要在 NA's' 中重新编码 -20-35
    【解决方案4】:

    这就是你所追求的吗?

    bar.sum <- ddply(bar, .(date), transform,
                     XYZmin.sum = cumsum(XYZmin))
    bar.sum
    

    【讨论】:

    • 非常感谢!这正是我想要的,我会尽快接受。谢谢!
    猜你喜欢
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-27
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    • 1970-01-01
    相关资源
    最近更新 更多