我需要一种更快/矢量化的方式来实现以下b / c,对于具有数百万个条目的大型数据集,循环需要很长时间。但到目前为止,没有任何好处出现在我的脑海里。
df <- data.frame(
id = c(1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4),
t = c(1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 1, 2, 3, 1, 2, 3),
tag = c(0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0),
tag2 = 0 # this is supposed to be computed
)
tag_items <- function(df) {
is1 <- FALSE
item <- -1
for(i in nrow(df):1) {
curr <- df[i,"tag"]
if(curr == 0) {
if(item != df[i,"id"]) {
is1 <- FALSE
item <- -1
} else {
if(is1) {
df[i,"tag2"] <- 1
} else {
df[i,"tag2"] <- 0
}
}
} else if(curr == 1) {
is1 <- TRUE
item <- df[i,"id"]
df[i,"tag2"] <- 1
}
}
return(df)
}
应用了标记:
> tag_items(df)
id t tag tag2
1 1 1 0 1
2 1 2 0 1
3 1 3 1 1
4 1 4 0 0
5 2 1 0 1
6 2 2 0 1
7 2 3 1 1
8 2 4 0 0
9 2 5 0 0
10 2 6 0 0
11 3 1 1 1
12 3 2 0 0
13 3 3 0 0
14 4 1 0 0
15 4 2 0 0
16 4 3 0 0
口头解释:
df
按时间顺序按id
和t
(ime)排序。对于给定的id
,tag2
的值应该为1,如果有一个值为tag
的条目为1,或者tag
为1为同一个条目
一种可能的方法是:按ID划分 - > FOCB - &gt;未分裂 - 但我怀疑由于顺序FOCB,该方法不会很快。
FOCB =向后进行第一次观察(LOCF转身)
答案 0 :(得分:3)
尝试
library(data.table)
setkey(setDT(df), id)[,tag2:=replace(tag2, seq(which(tag==1)),1) , by=id]
df
# id t tag tag2
#1: 1 1 0 1
#2: 1 2 0 1
#3: 1 3 1 1
#4: 1 4 0 0
#5: 2 1 0 1
#6: 2 2 0 1
#7: 2 3 1 1
#8: 2 4 0 0
#9: 2 5 0 0
#10: 2 6 0 0
#11: 3 1 1 1
#12: 3 2 0 0
#13: 3 3 0 0
#14: 4 1 0 0
#15: 4 2 0 0
#16: 4 3 0 0
或使用dplyr
library(dplyr)
df %>%
group_by(id) %>%
mutate(tag2= replace(tag2, seq(which(tag==1)),1))
答案 1 :(得分:1)
在cumsum
目标向量上使用rev
的另一种可能性,然后rev
得出结果:
library(dplyr)
df %>%
group_by(id) %>%
mutate(tag2 = rev(cumsum(rev(tag))))
# id t tag tag2
# 1 1 1 0 1
# 2 1 2 0 1
# 3 1 3 1 1
# 4 1 4 0 0
# 5 2 1 0 1
# 6 2 2 0 1
# 7 2 3 1 1
# 8 2 4 0 0
# 9 2 5 0 0
# 10 2 6 0 0
# 11 3 1 1 1
# 12 3 2 0 0
# 13 3 3 0 0
# 14 4 1 0 0
# 15 4 2 0 0
# 16 4 3 0 0
或在data.table
中应用相同的功能:
library(data.table)
setkey(setDT(df), id)[ , tag2 := rev(cumsum(rev(tag))), by = id]