如何计算R中每组的初始值的差异?

Tho*_*mas 5 r

我在R中安排了这样的数据:

indv    time    val
A          6    5
A         10    10
A         12    7
B          8    4
B         10    3
B         15    9
Run Code Online (Sandbox Code Playgroud)

对于每次每个人(indv),我想val从初始时间计算值()的变化.所以我最终得到这样的东西:

indv time   val val_1   val_change
A       6     5    5       0
A      10    10    5       5
A      12     7    5       2
B       8     4    4       0
B      10     3    4      -1
B      15     9    4       5
Run Code Online (Sandbox Code Playgroud)

有人能告诉我怎么做这个吗?我可以用

ddply(df, .(indv), function(x)x[which.min(x$time), ])
Run Code Online (Sandbox Code Playgroud)

得到一张像这样的桌子

indv    time    val
A          6    5   
B          8    4   
Run Code Online (Sandbox Code Playgroud)

但是,我无法弄清楚如何制作一个列val_1,其中每个人的最小值匹配.但是,如果我可以这样做,我应该可以val_change使用以下内容添加列:

df['val_change'] = df['val_1'] - df['val']
Run Code Online (Sandbox Code Playgroud)

编辑:下面发布了两个优秀的方法,但两者都依赖于我的时间列进行排序,以便小时间值在高时间值之上.我不确定我的数据总是如此.(我知道我可以先在Excel中排序,但我试图避免这种情况.)当表格显示如下时,我怎么能处理一个案例:

indv    time    value
A          10   10
A           6   5
A          12   7
B           8   4
B          10   3
B          15   9
Run Code Online (Sandbox Code Playgroud)

mne*_*nel 5

这是一个data.table内存高效的解决方案,因为它在data.table中通过引用进行设置.设置密钥将按关键变量排序

library(data.table)
DT <- data.table(df)  
# set key to sort by indv then time
setkey(DT, indv, time)
DT[, c('val1','change') := list(val[1], val - val[1]),by = indv]
# And to show it works....
DT
##    indv time val val1 change
## 1:    A    6   5    5      0
## 2:    A   10  10    5      5
## 3:    A   12   7    5      2
## 4:    B    8   4    4      0
## 5:    B   10   3    4     -1
## 6:    B   15   9    4      5
Run Code Online (Sandbox Code Playgroud)


Jil*_*ina 4

这是一个 plyr 解决方案,使用ddply

ddply(df, .(indv), transform, 
      val_1 = val[1],
      change = (val - val[1]))

  indv time val val_1 change
1    A    6   5     5      0
2    A   10  10     5      5
3    A   12   7     5      2
4    B    8   4     4      0
5    B   10   3     4     -1
6    B   15   9     4      5
Run Code Online (Sandbox Code Playgroud)

要获得第二张桌子,请尝试以下操作:

ddply(df, .(indv), function(x) x[which.min(x$time), ])
  indv time val
1    A    6   5
2    B    8   4
Run Code Online (Sandbox Code Playgroud)

编辑1

要处理未排序的数据,例如您在编辑中发布的数据,请尝试以下操作

unsort <- read.table(text="indv    time    value
A          10   10
A           6   5
A          12   7
B           8   4
B          10   3
B          15   9", header=T)


do.call(rbind, lapply(split(unsort, unsort$indv), 
                  function(x) x[order(x$time), ]))
    indv time value
A.2    A    6     5
A.1    A   10    10
A.3    A   12     7
B.4    B    8     4
B.5    B   10     3
B.6    B   15     9
Run Code Online (Sandbox Code Playgroud)

现在您可以将上述过程应用于此排序的数据框

编辑2

对数据帧进行排序的一种更短的方法是使用sortBydoBy 包中的函数

library(doBy)
orderBy(~ indv + time, unsort)
  indv time value
2    A    6     5
1    A   10    10
3    A   12     7
4    B    8     4
5    B   10     3
6    B   15     9
Run Code Online (Sandbox Code Playgroud)

编辑3

您甚至可以使用对 df 进行排序ddply

ddply(unsort, .(indv, time), sort)
  value time indv
1     5    6    A
2    10   10    A
3     7   12    A
4     4    8    B
5     3   10    B
6     9   15    B
Run Code Online (Sandbox Code Playgroud)