我有一些时间来处理数据,我想根据事件更改特定变量。在帮助下,我能够弄清楚如何更改一次值,但我希望能够不断更改它。以下是我开始使用的数据。
Time Event1 Event2 ID_1 ID_2 ID_3 ID_4 ID_5
1 0 0 1 1 1 1 0
2 0 0 1 1 1 1 0
3 0 0 1 1 1 1 0
4 0 0 1 1 1 1 0
5 ID_2 ID_5 1 1 1 1 0
6 0 0 1 1 1 1 0
7 ID_5 ID_2 1 1 1 1 0
8 0 0 1 1 1 1 0
我想要发生的事情是,当一个ID_X出现在Event1中时,我想将该变量中的所有未来值更改为0 UNTIL它们再次出现在Event2中,在这种情况下我想将它们翻转回1以下是我要做的事。
更新数据表
Time Event1 Event2 ID_1 ID_2 ID_3 ID_4 ID_5
1 0 0 1 1 1 1 0
2 0 0 1 1 1 1 0
3 0 0 1 1 1 1 0
4 0 0 1 1 1 1 0
5 ID_2 ID_5 1 0 1 1 1
6 0 0 1 0 1 1 1
7 ID_5 ID_2 1 1 1 1 0
8 0 0 1 1 1 1 0
正如你所看到的,ID_2出现在Event1中,开始变为0,然后出现在Event2中,应该被翻转回1.我唯一能够找到帮助的是如何从其余数据为1/0。但是,当我需要来回改变时,我不会认为我所做的事情(使用融化和重塑数据)会起作用。任何帮助都会很棒。感谢。
答案 0 :(得分:1)
这可以使用cumsum()
的组合来记录"ID_2"
的外观,例如Event1
或Event2
,和xor()
翻转。
library(data.table)
DT[, ID_2 := 0L + xor(cumsum(Event1 == "ID_2") - cumsum(Event2 == "ID_2"), ID_2)][]
DT[, ID_5 := 0L + xor(cumsum(Event1 == "ID_5") - cumsum(Event2 == "ID_5"), ID_5)][]
Time Event1 Event2 ID_1 ID_2 ID_3 ID_4 ID_5 1: 1 0 0 1 1 1 1 0 2: 2 0 0 1 1 1 1 0 3: 3 0 0 1 1 1 1 0 4: 4 0 0 1 1 1 1 0 5: 5 ID_2 ID_5 1 0 1 1 1 6: 6 0 0 1 0 1 1 1 7: 7 ID_5 ID_2 1 1 1 1 0 8: 8 0 0 1 1 1 1 0 9: 9 ID_2 0 1 0 1 1 0 10: 10 0 0 1 0 1 1 0 11: 11 0 ID_2 1 1 1 1 0 12: 12 0 0 1 1 1 1 0
请注意,示例数据集中添加了其他行,以证明ID_2
第二次翻转。
如果有多个ID_x
列,则可以使用lapply()
id_cols <- stringr::str_subset(names(DT), "^ID")
invisible(lapply(id_cols, function(col)
DT[, (col) := 0L + xor(cumsum(Event1 == col) - cumsum(Event2 == col), get(col))]))
DT[]
结果与上述相同。
使用 data.table
是因为它允许更新单个列到位,即不复制整个数据集,从而节省了内存和时间。 invisible()
会阻止打印lapply()
的结果。 <{1}}的结果在此处不需要,因为lapply()
已就地更新。
代码适用于给定的示例。它依赖于假设每个DT
在ID_x
和Event1
中交替显示,否则可能会失败。
下面的版本包括一个检查,如果违反了上述先决条件,则暂停执行(但不是最好的自解释错误消息):
Event2
由OP提供加上四行。
id_cols <- stringr::str_subset(names(DT), "^ID")
invisible(lapply(id_cols, function(col)
DT[, (col) := {
tmp <- cumsum(Event1 == col) - cumsum(Event2 == col)
stopifnot(all(tmp %in% -1:1))
0L + xor(tmp, get(col))
}]))
DT[]