我有一个data.frame,在多个时间点为每个主题测量一个值。它简化了这个:
> set.seed(42)
> x = data.frame(subject=rep(c('a', 'b', 'c'), 3), time=rep(c(1,2,3), each=3), value=rnorm(3*3, 0, 1))
> x
subject time value
1 a 1 1.37095845
2 b 1 -0.56469817
3 c 1 0.36312841
4 a 2 0.63286260
5 b 2 0.40426832
6 c 2 -0.10612452
7 a 3 1.51152200
8 b 3 -0.09465904
9 c 3 2.01842371
我想计算每个时间点和每个主题的value
变化。对于这个简单的例子,我目前的解决方案是:
> x$diff[x$time==1] = x$value[x$time==2] - x$value[x$time==1]
> x$diff[x$time==2] = x$value[x$time==3] - x$value[x$time==2]
> x
subject time value diff
1 a 1 1.37095845 -0.7380958
2 b 1 -0.56469817 0.9689665
3 c 1 0.36312841 -0.4692529
4 a 2 0.63286260 0.8786594
5 b 2 0.40426832 -0.4989274
6 c 2 -0.10612452 2.1245482
7 a 3 1.51152200 NA
8 b 3 -0.09465904 NA
9 c 3 2.01842371 NA
...然后删除最后一行。但是,在我的实际数据集中,time
的级别更高,我需要为多个列而不是value
执行此操作。代码变得非常难看。有一个巧妙的方法来做到这一点? 1}}中没有假设行在主题内排序的解决方案会很好。
答案 0 :(得分:4)
我们可以使用data.table
。将'data.frame'转换为'data.table'(setDT(x)
),按'subject'分组,我们将下一个值(shift(value, type='lead')
)的差值与当前值和assign({ {1}})输出以创建“Diff”列。
:=
答案 1 :(得分:3)
您可以尝试ave
。 ave
将函数应用于值的子集,有关详细信息,请参阅?ave
,例如:
x$diff <- ave(x$value, x$subject, FUN=function(x)c(diff(x), NA))
x
# subject time value diff
# 1 a 1 1.37095845 -0.7380958
# 2 b 1 -0.56469817 0.9689665
# 3 c 1 0.36312841 -0.4692529
# 4 a 2 0.63286260 0.8786594
# 5 b 2 0.40426832 -0.4989274
# 6 c 2 -0.10612452 2.1245482
# 7 a 3 1.51152200 NA
# 8 b 3 -0.09465904 NA
# 9 c 3 2.01842371 NA
BTW diff
函数要求订购time
。
编辑:使用set.seed(42)
更新。
答案 2 :(得分:3)
您可以使用dplyr
:
library(dplyr)
x %>%
arrange(time, subject) %>%
group_by(subject) %>%
mutate(diff = c(diff(value), NA))
# Source: local data frame [9 x 4]
# Groups: subject [3]
#
# subject time value diff
# (fctr) (dbl) (dbl) (dbl)
# 1 a 1 1.30970525 -1.66596287
# 2 b 1 0.12556761 -0.06070412
# 3 c 1 -1.09423634 1.38590546
# 4 a 2 -0.35625763 0.91417329
# 5 b 2 0.06486349 0.06652424
# 6 c 2 0.29166912 -0.98495562
# 7 a 3 0.55791566 NA
# 8 b 3 0.13138773 NA
# 9 c 3 -0.69328649 NA
如果您想摆脱NA
,请添加%>% na.omit
。