根据ID获取差异

时间:2016-07-11 10:31:57

标签: r

我的df有212行,形式为:

ID visit treatment value1 value2 value3
1    V0      A        2.6     3.4   .1
1    V1      A        2.3     4.6   .5
2    V0      B        1.3     5.4   .6
3    V0      A        1.6     5.4   .7
2    V1      B        1.8     4.5   .3
3    V1      A        1.3     7.3   1.2

所以o有一个带有ID的列,一个带访问周和处理的列以及一堆带有值的列。我想对每个ID采取差异,每个ID的处理方式相同,它从第0周和第1周开始不会改变.ID不一定按顺序排列。这可能吗?

这将是:

ID visit treatment value1 value2 value3
 1  v0-v1    A       0.3   -1.2     -.4

等等。

4 个答案:

答案 0 :(得分:4)

这是一个data.table解决方案:

dt[by=.(ID,treatment),j={
    z <- nrow(.SD);
    c(
        .(visit=paste0(visit[1L],'-',visit[z])),
        lapply(mget(grep(value=T,'^value',names(.SD))),function(x) x[1L]-x[z])
    );
}];
##    ID treatment visit value1 value2 value3
## 1:  1         A V0-V1    0.3   -1.2   -0.4
## 2:  2         B V0-V1   -0.5    0.9    0.3
## 3:  3         A V0-V1    0.3   -1.9   -0.5

数据

library(data.table);
dt <- data.table(ID=c(1L,1L,2L,3L,2L,3L),visit=c('V0','V1','V0','V0','V1','V1'),treatment=c(
'A','A','B','A','B','A'),value1=c(2.6,2.3,1.3,1.6,1.8,1.3),value2=c(3.4,4.6,5.4,5.4,4.5,7.3),
value3=c(0.1,0.5,0.6,0.7,0.3,1.2));

答案 1 :(得分:0)

我以csv的形式使用你的数据,分隔符只是为了测试代码。 假设我有一个名为inpstack的数据框中的数据

inpstack<-read.csv("/XXX/input.csv",header=TRUE)
library("sqldf")
stack1<-sqldf("select * from inpstack where visit='V0'");
stack2<-sqldf("select * from inpstack where visit='V1'");
stack3<-sqldf("select a.ID, 'V0-V1' as visit,(a.value1-b.value1) as value1,(a.value2-b.value2) as value2,(a.value3-b.value3) as value3 from stack1 a join stack2 b on a.ID=b.ID")

stack3 df具有以下输出

ID,visit,value1,value2,value3
1,V0-V1,0.3,-1.2,-0.4
2,V0-V1,-0.5,0.9,0.3
3,V0-V1,0.3,-1.9,-0.5

希望这会有所帮助。我使用过sqldf库

这仅适用于上述情况,即只有2次访问V0和V1

答案 2 :(得分:0)

也许这很有用

library(dplyr)
result <- df %>% group_by(ID,treatment) %>% summarise_each(funs(diff,toString(visit)),value1,value2,value3)
result[1:6]

答案 3 :(得分:0)

如果每次ID处理只有两次访问,您可以使用aggregate,如下所示:

aggregate(cbind(value1, value2, value3)~ID + treatment, data=df, function(i) i[1L]-i[2L])
  ID treatment value1 value2 value3
1  1         A    0.3   -1.2   -0.4
2  3         A    0.3   -1.9   -0.5
3  2         B   -0.5    0.9    0.3

如果集合不平衡,您可以插入一个返回NA或其他值的if语句:

aggregate(cbind(value1, value2, value3)~ID + treatment,
          data=df, function(i) {if(length(i) == 2L) i[1L]-i[2L] else NA})