给定一个数据框如下:

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 的值为:
  • 对于给定 ID(第 4 行和第 9 行),“p”从 a 变为 b 的行为零(我可以这样做)
  • 在每个唯一的 id 中,当 p 为 'a' 时,ta 的值应该从 0 开始倒数,计算出相关行与其上方行之间 t 的变化。例如,对于第 3 行,ta 的值应为 0 - (11-9) = -2。
  • 在每个唯一的 id 中,当 p 是 'b' 时,ta 的值应该从 0 开始计算相关行和它下面的行之间 t 的变化。例如,对于第 5 行,ta 的值应为 0 + (12-11) = 1。

  • 因此,完成后,数据框应如下所示:
    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/

    10-12 21:07