当前obs等于同一变量的下一个obs时的cumsum(列)

时间:2014-12-18 14:40:54

标签: r

我想在数据框中添加一个列,如果另一个变量对于两行相等,则会产生另一个变量的累计和。例如:

  Row   Var1    Var2    CumVal
  1 A 2 2
  2 A 4 6
  3 B 5 5      

所以我希望CumVal累积/求和Var2列,如果第2行的Var1 obs等于第1行Var1,则换句话说,如果是等于之前的obs。

2 个答案:

答案 0 :(得分:1)

如果cumsum基于Var1作为分组变量

library(dplyr)
 df %>% 
    group_by(Var1) %>% 
    mutate(CumVal=cumsum(Var2))

或者

library(data.table)
 setDT(df)[, CumVal:=cumsum(Var2), by=Var1]

或使用base R

transform(df, CumVal=ave(Var2, Var1, FUN=cumsum))

更新

如果是基于相邻元素是否不相等

transform(df, CumVal= ave(Var2, cumsum(c(TRUE,Var1[-1]!= 
                                  Var1[-nrow(df)])), FUN=cumsum))

#    Row Var1 Var2 CumVal
#1   1    A    2      2
#2   2    A    4      6
#3   3    B    5      5
#4   4    A    6      6

dplyr方法

df %>% 
   group_by(indx= cumsum(c(TRUE,(lag(Var1)!=Var1)[-1]))) %>%
   mutate(CumVal=cumsum(Var2)) %>%
   ungroup() %>% 
   select(-indx)

数据

df <- structure(list(Row = 1:4, Var1 = c("A", "A", "B", "A"), Var2 = c(2L, 
4L, 5L, 6L)), .Names = c("Row", "Var1", "Var2"), class = "data.frame", 
row.names = c(NA, -4L))

答案 1 :(得分:0)

我喜欢rle,它会检测向量中的类似连续值并以合成的方式描述它。例如。我们说我们有一个长度为10的向量x

x <- c(2, 3, 2, 2, 2, 2, 0, 0, 2, 1)

rle能够检测到有4个连续的2和2个连续的0:

rle(x)

# Run Length Encoding
#   lengths: int [1:6] 1 1 4 2 1 1
#   values : num [1:6] 2 3 2 0 2 1

(在输出中,我们可以有2个长度不同于1对应于值4和2)

我们可以使用此函数将cumsum应用于另一个向量的子向量。我们假设我们要在新的向量cumcum上应用y <- 1:10,但仅适用于x的重复值(将存储在因子f中) :

y <- 1:10
z <- rle(x)$lengths
f <- factor(rep( seq_along(z), z) )

然后,我们可以使用bytapply(或其他内容来实现所需的输出):

cumval <- unlist(tapply(y, f, cumsum))