使用示例描述我想要做的事情可能更容易......说我有以下数据框:
id1 id2 var
1 2 a
2 3 b
2 1 a
3 2 a
2 3 a
4 2 a
3 1 b
您可以按如下方式生成
df <- data.frame(id1 = c(1,2,2,3,2,4,3),
id2 = c(2,3,1,2,3,2,1),
var = c('a','b','a','a','a','a','b'))
我想要id2在id1中出现的累计次数与同样的var一样,所以我最终会用
id1 id2 var count
1 2 a 0
2 3 b 0
2 1 a 1
3 2 a 1
2 3 a 1
4 2 a 2
3 1 b 0
因此,第3行中的计数为1,因为我们在第3行(第1行)之前看到id1 = 1和var ='a',然后在第4行中,计数也是1,因为我们看到id1 = 2和var第3行中的“a”(我们只在第4行之前检查,因此不计算我们在第5行中看到的那个)。
如果我检查id1出现在id1中的次数,我会做类似
的事情with(df, ave(id1 == id1, paste(id1, var), FUN = cumsum))
对于id2,有一种快速简便的方法吗?
提前致谢
答案 0 :(得分:4)
可能有更优雅的方法,但这可以完成工作。这里的关键是split<-
函数。
df$count <- NA # This column must be added prior to calling `split<-`
# because otherwise we can't assign values to it
split(df, df$var) <- lapply(split(df, df$var), function(x){
x$count <- cumsum(sapply(1:nrow(x), function(i) x$id2[i] %in% x$id1[1:i]))
x
})
结果如下。存在一些差异,因此您在手动构建期望结果时遇到了一些错误,或者我误解了这个问题。
id1 id2 var count
1 1 2 a 0
2 2 3 b 0
3 2 1 a 1
4 3 2 a 2
5 2 3 a 3
6 4 2 a 4
7 3 1 b 0
<强>更新强>
为了使这个答案完整而有效,这是我对你的解决方案的看法。基本相同,但我认为ave
内lapply
更好,更可读。
df$count <- NA
split(df, df$var) <- lapply(split(df, df$var), function(x){
hit <- sapply(1:nrow(x), function(i) x$id2[i] %in% x$id1[1:i])
x$count <- ave(hit, x$id2, FUN=cumsum)
x
})
答案 1 :(得分:1)
使用和编辑了Backlin的答案以获得我想要的,代码如下
df$count<- NA
split(df, df$var) <- lapply(split(df, df$var), function(x){
x$count<- sapply(1:nrow(x), function(i) sum(x$id2[i] == x$id1[1:i]))
x
})
这可能是一种更优雅的方式,但我觉得这很有效......