ID累计滞后

时间:2019-05-27 00:21:46

标签: r datatable cumulative-sum multiple-conditions

我想通过ID创建一个累加的总和。但是,它不应将属于正在计算的行的值相加。

我已经尝试过cumsum。但是,我不知道如何添加一条语句,该语句指定不添加进行求和的行的数量。我要查找的结果列是名为“ sum”的第三列。

例如,对于ID 1,第一行是sum = 0,因为不应添加此行。但是,对于ID 1和第2行,sum = 100,因为第2行之前的ID 1的数量为100,依此类推。

   id amount sum
1:  1    100   0
2:  1     20 100
3:  1    150 120
4:  2     60   0
5:  2    100  60
6:  1     30 270
7:  2     40 160 

这是我尝试过的:

  df[,sum:=cumsum(amount),
      by ="id"] 

  data: df <- data.table(id = c(1, 1, 1, 2, 2,1,2), amount = c(100, 20, 
  150,60,100,30,40),sum=c(0,100,120,0,60,270,160) ,stringsAsFactors = 
  FALSE)

4 个答案:

答案 0 :(得分:5)

您可以不使用lag

> df %>%
      group_by(id) %>%
      mutate(sum = cumsum(amount) - amount)
# A tibble: 7 x 3
# Groups:   id [2]
     id amount   sum
  <dbl>  <dbl> <dbl>
#1    1    100     0
#2    1     20   100
#3    1    150   120
#4    2     60     0
#5    2    100    60
#6    1     30   270
#7    2     40   160

答案 1 :(得分:2)

使用dplyr-

df %>% 
  group_by(id) %>% 
  mutate(sum = lag(cumsum(amount), default = 0)) %>% 
  ungroup()

# A tibble: 7 x 3
     id amount   sum
  <dbl>  <dbl> <dbl>
1     1    100     0
2     1     20   100
3     1    150   120
4     2     60     0
5     2    100    60
6     1     30   270
7     2     40   160

感谢@thelatemail,这里是data.table版本-

df[, sum := cumsum(shift(amount, fill=0)), by=id]

答案 2 :(得分:1)

这是base R

中的一个选项
df$Sum <- with(df, ave(amount, id, FUN = cumsum) - amount)
df$Sum
#[1]   0 100 120   0  60 270 160

或者通过删除最后一个观察值,取cumsum

with(df, ave(amount, id, FUN  = function(x) c(0, cumsum(x[-length(x)]))))

答案 3 :(得分:0)

您可以使用lag函数来移动求和的值。

library(tidyverse)

df <- data.frame(id = c(1, 1, 1, 2, 2,1,2), amount = c(100, 20, 
150,60,100,30,40),sum=c(0,100,120,0,60,270,160) ,stringsAsFactors = 
FALSE)

df %>% 
    group_by(id) %>% 
    mutate(sum = cumsum(lag(amount, 1, default=0)))

# A tibble: 7 x 3
# Groups:   id [2]
     id amount   sum
  <dbl>  <dbl> <dbl>
1     1    100     0
2     1     20   100
3     1    150   120
4     2     60     0
5     2    100    60
6     1     30   270
7     2     40   160