我有一个数据表“DT”。现在,我想使列A1:B3等于前一行,然后根据条件更新值,给出整个第一行。每列中没有模式。
ID title action value A1 A2 A3 B1 B2 B3
1: 1 A3 1 15 7 9 15 45 20 62
2: 2 A1 0 22 NA NA NA NA NA NA
3: 3 B2 1 92 NA NA NA NA NA NA
4: 4 A2 0 17 NA NA NA NA NA NA
5: 8 B1 1 55 NA NA NA NA NA NA
6: 6 B3 1 37 NA NA NA NA NA NA
7: 12 B2 0 16 NA NA NA NA NA NA
8: 8 A1 1 35 NA NA NA NA NA NA
9: 9 B3 1 13 NA NA NA NA NA NA
从第2行到第9行,我想为每一行j,我想
DT[j, A1:B3]=DT[j-1, A1:B3]
然后根据每个相应行中的值更新A1:B3。要更新的元素来自名为“title”的相应列。
对于第2行,从A1
到B3
,从前一行复制7 9 15 45 20 62
,然后更改A1
(DT[2, title]
提供此信息),{ {1}}为DT[2, action]
,因此我们将0
插入22
,然后将A1
移至7
,将A2
移至{{} 1}},删除原始9
。 A3
变为A3
(以DT[2, A1:B3]
开头的列名称无法推送到22 7 9 45 20 62
。)。如果'A'
为'B'
,则只需替换。
处理完毕后,所需的输出应如下所示:
DT[2, action]
我现在正在使用一个循环来执行此操作,但它非常慢,并且仅在1
时才有效,当 ID title action value A1 A2 A3 B1 B2 B3
1: 1 A3 1 15 7 9 15 45 20 62
2: 2 A1 0 22 22 7 9 45 20 62
3: 3 B2 1 92 22 7 9 45 92 62
4: 4 A2 0 17 22 17 7 45 92 62
5: 8 B1 1 55 22 17 7 55 92 62
6: 6 B3 1 37 22 17 7 55 92 37
7: 12 B2 0 16 22 17 7 55 16 92
8: 8 A1 1 35 35 17 7 55 16 92
9: 9 B3 1 13 35 17 7 55 16 13
时,我不确定如何挤入新值。< / p>
action == 1
当action == 0
为for (j in 2:nrow(DT)){
DT[j, A1:B3] <- DT[j-1, A1:B3]
if(DT$action[j] == 1) {
position <- which.first(colnames(DT) == DT$title[j], use.names = TRUE)
DT[j,position] <- DT$value[j]
}
}
时,它很简单,当action
为1
时,可能会造成混淆。
随时留下评论或参考所需的输出。我很乐意做更多的解释。
答案 0 :(得分:1)
由于以下几个原因,这是一个棘手的问题:
下面的方法将数据从宽格式转换为长格式,因为(2.)使我们能够使用append()
函数插入值列式。它使用for
循环,因为(1.)和set()
函数通过引用更新,即不复制整个数据对象:
# append row number, then reshape from wide to long format
long <- melt(DT[, rn := .I], measure.vars = patterns("^[AB]\\d"), value.name = "val")[order(rn)]
for (i in seq_len(nrow(DT) - 1L) + 1L){
# copy the row values from previous row
set(long, long[rn == i, which = TRUE], "val", long[rn == (i - 1L), .(val)])
# update values depending on action indicator
if (long[rn == i, first(action) == 1]) {
# replace selected value
idx <- long[rn == i & variable == title, which = TRUE]
set(long, idx, "val", long[idx[1L], value])
} else {
# insert selected value
pat <- paste0("^", long[rn == i, stringi::stri_sub(first(title), 1L, 1L)])
idx <- long[rn == i & variable %like% pat, which = TRUE]
set(long, idx, "val",
head( # drop last element after insert
append(long[idx, val], long[idx[1L], value],
after = long[idx[1L], as.integer(stringi::stri_sub(title, 2L)) - 1L]),
-1L))
}
}
# reshape back to wide format
dcast(long, rn + ... ~ variable, value.var = "val")[, rn := NULL][]
ID title action value A1 A2 A3 B1 B2 B3 1: 1 A3 1 15 7 9 15 45 20 62 2: 2 A1 0 22 22 7 9 45 20 62 3: 3 B2 1 92 22 7 9 45 92 62 4: 4 A2 0 17 22 17 7 45 92 62 5: 8 B1 1 55 22 17 7 55 92 62 6: 6 B3 1 37 22 17 7 55 92 37 7: 12 B2 0 16 22 17 7 55 16 92 8: 8 A1 1 35 35 17 7 55 16 92 9: 9 B3 1 13 35 17 7 55 16 13