我的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
等等。
答案 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})