我有以下数据:
set.seed(2)
d <- data.frame(iteration=c(1,1,2,2,2,3,4,5,6,6,6),
value=sample(11),
var3=sample(11))
iteration value var3
1 1 3 7
2 1 8 4
3 2 6 8
4 2 2 3
5 2 7 9
6 3 9 11
7 4 1 10
8 5 4 1
9 6 10 2
10 6 11 6
11 6 5 5
现在,我想要以下内容: 1. IF 有更多比一次迭代删除最后行并替换最后行的值与之前的值。 所以在上面的示例中,这是我想要的输出:
d<-data.frame(iteration=c(1,2,2,3,4,5,6,6),
value=c(8,6,7,9,1,4,10,5))
iteration value var3
1 1 8 7
2 2 6 8
3 2 7 3
4 3 9 11
5 4 1 10
6 5 4 1
7 6 10 2
8 6 5 6
答案 0 :(得分:3)
我们可以使用data.table
library(data.table)
setDT(d)[, .(value = if(.N>1) c(value[seq_len(.N-2)], value[.N]) else value), iteration]
# iteration value
#1: 1 8
#2: 2 6
#3: 2 7
#4: 3 9
#5: 4 1
#6: 5 4
#7: 6 10
#8: 6 5
根据OP帖子中的更新,我们可以先在&#39;值&#39;中创建一个lead
值的新列,然后分配&#39; value1&#39;价值&#39;仅适用于满足&#39; i1&#39;中的条件的人,然后对行进行子集
setDT(d)[, value1 := shift(value, type = "lead"), iteration]
i1 <- d[, if(.N >1) .I[.N-1], iteration]$V1
d[i1, value := value1]
d[d[, if(.N > 1) .I[-.N] else .I, iteration]$V1][, value1 := NULL][]
# iteration value var3
#1: 1 8 7
#2: 2 6 8
#3: 2 7 3
#4: 3 9 11
#5: 4 1 10
#6: 5 4 1
#7: 6 10 2
#8: 6 5 6
答案 1 :(得分:2)
使用split-apply-combine方法的这个基本R解决方案返回与@ akrun的data.table
版本相同的值,尽管逻辑似乎不同。
do.call(rbind, lapply(split(d, d$iteration),
function(i)
if(nrow(i) >= 3) i[-(nrow(i)-1),] else tail(i, 1)))
iteration value
1 1 8
2.3 2 6
2.5 2 7
3 3 9
4 4 1
5 5 4
6.9 6 10
6.11 6 5
我们的想法是将data.frame拆分为沿迭代的data.frames列表,然后对于每个data.frame,检查是否有超过2行,如果是,则抓住第一行和最后一行,如果没有,然后只返回最后一行。 do.call
rbind
然后将这些观察结果编译成单个data.frame。
请注意,这在其他变量存在的情况下不起作用。