研究员R-Stackoverflowers,
我有一个包含2列的数据表,我试图根据现有的2个列值和前一行的新列计算值计算新的第三列。
我一直在查看论坛,我已经尝试了几个答案,但我没有做好。我希望你能帮助我。
这是一个可重复的例子:
xmlHttp.send
"期待"列包含我期望用"错误"计算的值。和"触发"列。我想申请的公式如下:
error <- c(1,1,0,0,0,1,1,1,1,0)
trigger <- c(FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE)
expected <- c(1,2,0,0,0,1,2,3,4,0)
DTtest <- data.table(error, trigger, expected)
DTtest
error trigger expected
1: 1 FALSE 1
2: 1 TRUE 2
3: 0 FALSE 0
4: 0 FALSE 0
5: 0 FALSE 0
6: 1 FALSE 1
7: 1 TRUE 2
8: 1 TRUE 3
9: 1 TRUE 4
10: 0 FALSE 0
我的第一次尝试是直接使用ifelse来更新新列。我发现我必须初始化新列才能运行它:
if(trigger) {
new_column = new_column(previous_row) + 1
} else {
new_column = error
}
此选项会计算新列&#34;影响&#34;但是结果与我在Excel中计算列的预期值不匹配(我可以对整个数据表进行处理,因为它非常大):
DTtest <- DTtest[, impact:=0]
DTtest[, impact:=ifelse(trigger, lag(impact)+1, error)]
然后我尝试了for循环,但结果也不正确:
error trigger expected impact
1: 1 FALSE 1 1
2: 1 TRUE 2 1
3: 0 FALSE 0 0
4: 0 FALSE 0 0
5: 0 FALSE 0 0
6: 1 FALSE 1 1
7: 1 TRUE 2 1
8: 1 TRUE 3 1
9: 1 TRUE 4 1
10: 0 FALSE 0 0
我觉得滞后(影响)由于某种原因没有获得更新的值,但我不明白为什么。
你能帮帮我吗?谢谢!
答案 0 :(得分:3)
这可能是代码高尔夫,但我喜欢我的代码详细:
DTtest[, impact := error]
#add a TRUE before each trigger run
DTtest[, trigger1 := trigger | shift(trigger, 1L, fill = FALSE, type = "lead")]
#IDs for by
DTtest[, rleid := rleid(trigger1)]
#cumsum by
DTtest[(trigger1), impact := cumsum(impact), by = rleid]
# error trigger expected impact trigger1 rleid
# 1: 1 FALSE 1 1 TRUE 1
# 2: 1 TRUE 2 2 TRUE 1
# 3: 0 FALSE 0 0 FALSE 2
# 4: 0 FALSE 0 0 FALSE 2
# 5: 0 FALSE 0 0 FALSE 2
# 6: 1 FALSE 1 1 TRUE 3
# 7: 1 TRUE 2 2 TRUE 3
# 8: 1 TRUE 3 3 TRUE 3
# 9: 1 TRUE 4 4 TRUE 3
#10: 0 FALSE 0 0 FALSE 4
答案 1 :(得分:1)
以下是使用群组的替代方法:
DTtest[, grp:=cumsum(!trigger)][,new:=c(error[1], cumsum(head(error, -1))+1),grp][]
error trigger expected grp new
1: 1 FALSE 1 1 1
2: 1 TRUE 2 1 2
3: 0 FALSE 0 2 0
4: 0 FALSE 0 3 0
5: 0 FALSE 0 4 0
6: 1 FALSE 1 5 1
7: 1 TRUE 2 5 2
8: 1 TRUE 3 5 3
9: 1 TRUE 4 5 4
10: 0 FALSE 0 6 0
答案 2 :(得分:0)
创建新的“虚拟”列,在触发器== TRUE
时复制错误DTtest[DTtest$trigger=="TRUE", "dummy"]<- DTtest[DTtest$trigger=="TRUE", "error"]
DTtest[is.na(DTtest$dummy), "dummy"] <- 0 # replace NA in dummy column with 0
基于虚拟列的循环:
for(i in 1:nrow(DTtest)){
if(i == 1)DTtest[i, "new"] <- 0
else DTtest[i, "new"] <- DTtest[i,"dummy"] + DTtest[i-1,"new"]
}
error trigger expected dummy new
1 1 FALSE 1 0 0
2 1 TRUE 2 1 1
3 0 FALSE 0 0 1
4 0 FALSE 0 0 1
5 0 FALSE 0 0 1
6 1 FALSE 1 0 1
7 1 TRUE 2 1 2
8 1 TRUE 3 1 3
9 1 TRUE 4 1 4
10 0 FALSE 0 0 4