【问题标题】:Wrapping cumulative sum from a set starting row in R从R中的一组起始行包装累积总和
【发布时间】:2017-02-24 05:25:43
【问题描述】:

我有一个看起来有点像这样的数据框:

wt <- data.frame(region = c(rep("A", 5), rep("B", 5)), time = c(1:5, 1:5), 
                 start = c(rep(2,5), rep(4, 5)), value = rep(1, 10))

value 列中的值可以是任意数字(我正在处理一个非常大的数据集),但每个区域将在一个等长的时间序列上,并且有一个起点。

我想在每个区域内执行累积和,从起点开始累积,在时间序列中继续向前,并在时间序列中回绕到起点之前的行。

带有预期结果的完整数据表如下所示:

region    time     start    value    result
A         1        2        1        5
A         2        2        1        1
A         3        2        1        2
A         4        2        1        3
A         5        2        1        4
B         1        4        1        3
B         2        4        1        4
B         3        4        1        5
B         4        4        1        1
B         5        4        1        2

时间列的简单转换后跟cumsum 不起作用,因为该函数关心行顺序而不是任何特定因素。

考虑到这一点,我正在处理一个巨大的数据表,运行时绝对是一个问题,因此任何解决方案必须避免重新排序行。

关于如何做到这一点的想法?提前致谢。

编辑:将时间视为一个循环,例如一天中的几个小时 - 例如,如果开始时间为 2,则意味着观察从时间 2 的一个实例开始,并在下一个时间 1 结束。

【问题讨论】:

  • '结果的逻辑不清楚
  • @akrun value 列的累积从 time == start 开始到 time == start-1 结束。如果开始时间不是 1,则累积应该绕到该区域的第一行。
  • 在这种情况下,预期的输出似乎不正确。如果我们取区域'A',那么 time == start 是第二行,time==start-1 是第三行,
  • @akrun 怎么会这样?它在区域 A 的 time==2 和区域 B 的 time==4 上开始包装累积总和
  • 您说您想要“每个区域内的累积总和”,这意味着您不应该在第 4 次进入区域 B。您之前的评论不一致。这相当令人困惑:因为$region$start 完全混淆了,你的例子有点难以用来描述你的问题。您能否阐明您的分组逻辑或生成一个工作/可重现的样本数据集?

标签: r dataframe data.table


【解决方案1】:

我们可以通过data.table 有效地做到这一点

library(data.table)
setDT(wt)[time>=start, result := seq_len(.N), region]
wt[, Max := max(result, na.rm = TRUE), region]
wt[is.na(result), result := Max +seq_len(.N) , region][, Max := NULL][]
#   region time start value result
#1:      A    1     2     1      5
#2:      A    2     2     1      1
#3:      A    3     2     1      2
#4:      A    4     2     1      3
#5:      A    5     2     1      4
#6:      B    1     4     1      3
#7:      B    2     4     1      4
#8:      B    3     4     1      5
#9:      B    4     4     1      1
#10:     B    5     4     1      2

【讨论】:

  • 这看起来可行!代码中的哪个位置选择了value 列以计算结果?
  • @ctenochaetus 好的,我看到您的“值”列是一个序列,所以是的,如果有像您发布的那样的其他值,您可以将其更改为 cumsum
【解决方案2】:

akrun 的解决方案适用于我给出的示例(因此我接受它作为答案),但这里有一个适用于 value 列中的任何值的版本:

library(data.table)
setDT(wt)[time>=start, result := cumsum(value), region]
wt[, Max := max(result, na.rm = TRUE), region]
wt[is.na(result), result := Max +cumsum(value) , region][, Max := NULL][]

只需添加...不幸的是名为 cumsum 的函数来代替计算序列。

【讨论】:

    猜你喜欢
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 2020-11-03
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多