给定一个数据框如下:
id<-c(1,1,1,1,1,1,2,2,2,2,2,2)
t<-c(6,8,9,11,12,14,55,57,58,60,62,63)
p<-c("a","a","a","b","b","b","a","a","b","b","b","b")
df<-data.frame(id,t,p)
row id t p
1 1 6 a
2 1 8 a
3 1 9 a
4 1 11 b
5 1 12 b
6 1 14 b
7 2 55 a
8 2 57 a
9 2 58 b
10 2 60 b
11 2 62 b
12 2 63 b
我想创建一个新变量 'ta' 使得 ta 的值为:
因此,完成后,数据框应如下所示:
row id t p ta
1 1 6 a -5
2 1 8 a -3
3 1 9 a -2
4 1 11 b 0
5 1 12 b 1
6 1 14 b 3
7 2 55 a -3
8 2 57 a -1
9 2 58 b 0
10 2 60 b 2
11 2 62 b 4
12 2 63 b 5
我一直在玩循环和 cumsum() 以及 head() 和 tail() 并且不能完全使这种在 id/in 条件内求和工作。关于处理来自前一行或后一行的值还有许多其他问题,但我无法完全重塑任何这些技术以在这里工作。非常感谢您的想法。
最佳答案
干得好。这是一种 split-apply-combine 策略,通过 id
分解所有内容,建立 p=='a'
和 p=='b'
之间的过渡点,然后减去其上方和下方的值。仅当您的数据按照您在此处显示的方式实际排序时才有效。
do.call('rbind',
lapply(split(df, id), function(x) {
# save values of `0` at transition points in `p`
x <- cbind.data.frame(x, ta=ifelse(c(0,diff(as.numeric(as.factor(x$p))))==1, 0, NA))
# identify indices for those points
w <- which(x$ta==0)
# handle `ta` values for `p=='b'`
x$ta[(w+1):nrow(x)] <- x$ta[w] + (x$t[(w+1):nrow(x)] - x$t[w])
# handle `ta` values for `p=='a'`
x$ta[1:(w-1)] <- x$ta[w] - (x$t[w] - x$t[1:(w-1)])
return(x)
})
)
结果:
id t p ta
1.1 1 6 a -5
1.2 1 8 a -3
1.3 1 9 a -2
1.4 1 11 b 0
1.5 1 12 b 1
1.6 1 14 b 3
2.7 2 55 a -3
2.8 2 57 a -1
2.9 2 58 b 0
2.10 2 60 b 2
2.11 2 62 b 4
2.12 2 63 b 5
关于r - 在 R 中,如何根据前一行(或后一行)的更改为变量设置值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21867109/