根据序列中的位置分配新值

and*_*rey 5 for-loop if-statement r data-manipulation conditional-statements

在R.工作.数据跟踪大脑活动随时间的变化.列"标记"包含特定治疗开始和结束时的信息.例如,第一个条件(标记== 1)从第3行开始,到第6行结束.第二个实验条件(标记== 2)从第9行开始,到第12行结束.在行之间重复另一批处理1 15和18.

ob.id <- c(1:20)
mark <- c(0,0,1,0,0,1,0,0,2,0,0,2,0,0,1,0,0,1,0,0)
condition<-c(0,0,1,1,1,1,0,0,2,2,2,2,0,0,1, 1,1,1,0,0)
start <- data.frame(ob.id,mark)
result<-data.frame(ob.id,mark,condition)
print (start)
> print (start)
   ob.id mark
1      1    0
2      2    0
3      3    1
4      4    0
5      5    0
6      6    1
7      7    0
8      8    0
9      9    2
10    10    0
11    11    0
12    12    2
13    13    0
14    14    0
15    15    1
16    16    0
17    17    0
18    18    1
19    19    0
20    20    0
Run Code Online (Sandbox Code Playgroud)

我需要创建一个列,该列具有一个虚拟变量,指示相应实验条件下观察的成员资格,如下所示:

> print(result)
   ob.id mark condition
1      1    0         0
2      2    0         0
3      3    1         1
4      4    0         1
5      5    0         1
6      6    1         1
7      7    0         0
8      8    0         0
9      9    2         2
10    10    0         2
11    11    0         2
12    12    2         2
13    13    0         0
14    14    0         0
15    15    1         1
16    16    0         1
17    17    0         1
18    18    1         1
19    19    0         0
20    20    0         0
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助!

edd*_*ddi 4

这是一个有趣的小问题。我下面使用的技巧是首先计算rle向量的mark,这使得问题变得更简单,因为结果values向量始终只有一个 0,可能需要也可能不需要替换(取决于周围的值)。

# example vector with some edge cases
v = c(0,0,1,0,0,0,1,2,0,0,2,0,0,1,0,0,0,0,1,2,0,2)

v.rle = rle(v)
v.rle
#Run Length Encoding
#  lengths: int [1:14] 2 1 3 1 1 2 1 2 1 4 ...
#  values : num [1:14] 0 1 0 1 2 0 2 0 1 0 ...

vals = rle(v)$values

# find the 0's that need to be replaced and replace by the previous value
idx = which(tail(head(vals,-1),-1) == 0 & (head(vals,-2) == tail(vals,-2)))
vals[idx + 1] <- vals[idx]

# finally go back to the original vector
v.rle$values = vals
inverse.rle(v.rle)
# [1] 0 0 1 1 1 1 1 2 2 2 2 0 0 1 1 1 1 1 1 2 2 2
Run Code Online (Sandbox Code Playgroud)

也许最不麻烦的事情是将上述内容放入一个函数中,然后将其应用于您的data.frame向量(而不是显式操作向量)。


另一种方法基于 @SimonO101 的观察,涉及从起始数据构建正确的组(by逐个单独运行该部分,看看它是如何工作的):

library(data.table)
dt = data.table(start)

dt[, result := mark[1],
     by = {tmp = rep(0, length(mark));
           tmp[which(mark != 0)[c(F,T)]] = 1;
           cumsum(mark != 0) - tmp}]
dt
#    ob.id mark result
# 1:     1    0      0
# 2:     2    0      0
# 3:     3    1      1
# 4:     4    0      1
# 5:     5    0      1
# 6:     6    1      1
# 7:     7    0      0
# 8:     8    0      0
# 9:     9    2      2
#10:    10    0      2
#11:    11    0      2
#12:    12    2      2
#13:    13    0      0
#14:    14    0      0
#15:    15    1      1
#16:    16    0      1
#17:    17    0      1
#18:    18    1      1
#19:    19    0      0
#20:    20    0      0
Run Code Online (Sandbox Code Playgroud)

后一种方法可能会更加灵活。