计算每个ID的访问次数(cumsum),同时忽略NA和0

时间:2018-06-06 18:32:15

标签: r na cumsum

我有以下df:

df <- data.frame(ID = c(1,1,2,2,2,3,3,3,3),
                 Attendance = c(1, 1, NA, 1,1, NA, 1, NA, 1 ))

我想要这个:

df <- data.frame(ID = c(1,1,2,2,2,3,3,3,3),
                 Attendance = c(1, 1, NA, 1,1, NA, 1, NA, 1),
                 Visit = c(1,2,0,1,2,0,1,0,2))

如何在“访问”列中根据“出勤”列值显示ID(每次出现(cumsum)时),同时忽略NA或0?

我尝试使用 ave 这样的功能,但没有成功:

df$Visit <- ifelse(!is.na(df$ID), (ave(df$ID, df$ID, FUN=cumsum))/df$ID, 0)

我通过创建一个辅助df来实现结果:

aux <- df[complete.cases(df$Attendance),] 

使用 Ave 功能计算访问次数,然后合并,但我确信存在最简单的方法

2 个答案:

答案 0 :(得分:1)

我们可以使用data.table。转换&#39; data.frame&#39;到&#39; data.table&#39; (setDT(df)),按&#39; ID&#39;分组,将i指定为逻辑向量,对于非参考文献中的非NA元素为TRUE,分配( :=)&#39; rowid&#39;的出席情况&#39;作为&#39;访问&#39;柱。然后,在&#39;访问&#39;中替换NA。到0

library(data.table)
setDT(df)[!is.na(Attendance), Visit := rowidv(Attendance), 
                   ID][is.na(Visit), Visit := 0]
df
#   ID Attendance Visit
#1:  1          1     1
#2:  1          1     2
#3:  2         NA     0
#4:  2          1     1
#5:  2          1     2
#6:  3         NA     0
#7:  3          1     1
#8:  3         NA     0
#9:  3          1     2

或者,如果我们使用ave,则为非NA行创建索引,然后对这些行使用ave

i1 <- !is.na(df$Attendance)
df$Visit <- 0
df$Visit[i1] <- with(df[i1, ], ave(Attendance, ID, FUN = cumsum))

答案 1 :(得分:1)

library(dplyr)
df %>%
    group_by(ID) %>%
    mutate(Visit = if_else(is.na(Attendance), 0, cumsum(if_else(is.na(Attendance), 0, 1))))