我有以下R data.table,它只由一列组成:
library(data.table)
DT <- data.table(first_column = c(0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0))
> DT
first_column
1: 0
2: 0
3: 0
4: 1
5: 1
6: 1
7: 0
8: 0
9: 1
10: 1
11: 0
12: 0
13: 0
14: 0
15: 1
16: 1
17: 1
18: 1
19: 1
20: 0
21: 0
... ...
二进制列first_column
由连续列的“簇”组成。
我想为每个群集转动每个前面的0并将其转换为1.不知何故,一个检查1
,然后将前面的0更改为1.
编辑:为了更清楚,模式0001110011000011111...
将变为0011110111000111111...
答案 0 :(得分:2)
使用diff
:
DT$first_column[diff(DT$first_column)==1] <- 1
# first_column
# 1: 0
# 2: 0
# 3: 1
# 4: 1
# 5: 1
# 6: 1
# 7: 0
# 8: 1
# 9: 1
# 10: 1
# 11: 0
# 12: 0
# 13: 0
# 14: 1
# 15: 1
# 16: 1
# 17: 1
# 18: 1
# 19: 1
# 20: 0
# 21: 0
# first_column
基本上diff
只会在1
前面1
输出0
。
答案 1 :(得分:2)
这将取代每个0/1&#34;组的最终值&#34;使用1,这对于1组来说是多余的,但是你想要为0做什么(如果我正确地读了你的问题)。
DT[, c(head(first_column, -1), 1), by=rleid(first_column)]
rleid
用于对相邻的0和1进行分组,head
用-1保留除最终元素之外的所有元素。或者甚至更好,您可以像@Frank建议的那样使用replace
,就像这样
DT[, replace(first_column, .N, 1), by=rleid(first_column)]
其中.N
用于指定组中的最后一行。这两个都返回
rleid V1
1: 1 0
2: 1 0
3: 1 1
4: 2 1
5: 2 1
6: 2 1
7: 3 0
8: 3 1
9: 4 1
10: 4 1
11: 5 0
12: 5 0
13: 5 0
14: 5 1
15: 6 1
16: 6 1
17: 6 1
18: 6 1
19: 6 1
20: 7 0
21: 7 1
rleid V1
这些解决方案(错误地)用1填写最终观察结果。避免这种情况的一种方法是在填写值之前添加一个检查。
DT[, if(.I[.N] < nrow(DT)) replace(first_column, .N, 1) else first_column,
by=rleid(first_column)]
此处,.I[.N] < nrow(DT)
为除最终组之外的每个组返回TRUE。这个小组的最终观察结果是&#34;原样。&#34;
答案 2 :(得分:2)
如果我正确理解了OP,他希望将子序列0,1
的任何出现转变为1,1
:
DT <- data.table(first_column = c(0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0))
DT[first_column == 0 & shift(first_column, type = "lead") == 1, first_column := 1]
DT[, first_column]
# [1] 0 0 1 1 1 1 0 1 1 1 0 0 0 1 1 1 1 1 1 0 0
以double
到logical
的隐式类型转换为代价,可以更简洁地写成:
DT <- data.table(first_column = c(0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0))
DT[!first_column & shift(first_column, type = "lead"), first_column := 1]
DT[, first_column]
# [1] 0 0 1 1 1 1 0 1 1 1 0 0 0 1 1 1 1 1 1 0 0
此处使用的事实是0
被视为FALSE
,任何数字都不等于0
TRUE
。