如何在R中拆分/子集数据帧,根据拆分编辑数据,然后改革数据帧?

时间:2016-01-11 04:33:56

标签: r

我有一个数据框中的大数据集。这是一个示例(为简洁起见,我还省略了几列协变量):

id  week
1   5
1   7
1   8
1   9
1   10
1   11
1   14
1   15
1   16
1   17
1   18
2   3
2   5
2   6
2   7
2   9
2   10
2   11
2   14
2   15
2   16
2   17
2   18
2   20
2   22
….. …..
8   8
11  8
14  8
16  8
18  8
21  8
22  8
25  8
26  8
27  8
36  8
37  8
3   9
4   9
5   9
7   9
8   9
9   9
10  9
11  9
14  9
15  9
17  9
18  9
22  9
23  9

我正在对这些数据进行一些生存分析,我需要以多种方式操纵数据。

首先,我需要添加一个列"事件"除了每个id的最后一行之外的所有行都取值0。例如,对于id = 1,行中的1对应于第18周,而其他行中为0。然后,等等所有约。 3000 ids。 我曾尝试过分裂'和'子集'但是我遇到了将数据恢复到原始数据框架的问题。

其次,我需要一个时间'对于每个id,为第一个(最小)周值取值1的列,然后以与周列相同的增量向上计数。以下两点的一个例子如下,即我想要最终得到的结果。 :

id  week event  time
1   5   0   1
1   7   0   3
1   8   0   4
1   9   0   5
1   10  0   6
1   11  0   7
1   14  0   10
1   15  0   11
1   16  0   12
1   17  0   13
1   18  1   14
2   3   0   1
2   5   0   3
2   6   0   4
2   7   0   5
2   9   0   7
2   10  0   8
2   11  0   9
2   14  0   12
2   15  0   13
2   16  0   14
2   17  0   15
2   18  0   16
2   20  0   18
2   22  1   20

第三,我需要采用这个新的数据集并创建一些新的列:每个周的假人'期。我需要37周'虚拟列,单元格中的1对应于'周'行和周虚拟列。

id  event   d1  d2  d3  d4  d5  d6  d7  d8  d9  covariate
1   0   0   0   0   0   1   0   0   0   0   0.70
1   0   0   0   0   0   0   0   1   0   0   0.56
1   0   0   0   0   0   0   0   0   1   0   0.70
1   0   0   0   0   0   0   0   0   0   1   0.16

我一直在尝试很多东西,主要是在过去几天的前两点,我仍处于学习曲线的陡峭部分。虽然变得更好。任何想法/评论等?谢谢!

2 个答案:

答案 0 :(得分:2)

我们可以使用data.table

library(data.table)
setDT(dfN)[order(id, week), c("event", "time") := list(+(1:.N==.N),
                      cumsum(c(1,diff(week))))  ,id]
dfN
#    id week event time
# 1:  1    5     0    1
# 2:  1    7     0    3
# 3:  1    8     0    4
# 4:  1    9     0    5
# 5:  1   10     0    6
# 6:  1   11     0    7
# 7:  1   14     0   10
# 8:  1   15     0   11
# 9:  1   16     0   12
#10:  1   17     0   13
#11:  1   18     1   14
#12:  2    3     0    1
#13:  2    5     0    3
#14:  2    6     0    4
#15:  2    7     0    5
#16:  2    9     0    7
#17:  2   10     0    8
#18:  2   11     0    9
#19:  2   14     0   12
#20:  2   15     0   13
#21:  2   16     0   14
#22:  2   17     0   15
#23:  2   18     0   16
#24:  2   20     0   18
#25:  2   22     1   20

或者

setDT(dfN)[order(id, week), c("event", "time") := list(c(rep(0,.N-1), 1),
                      cumsum(c(1,diff(week))))  ,id]

对于问题的第三部分,我们可以使用dcast

dfN[, week:=factor(week, levels=1:37)]
dfN[, N:= 1:.N]


 res <- dcast(dfN, N~week, value.var="time", length, drop=FALSE)[,
    c("id", "event") := dfN[, c("id", "event"), with=FALSE]][]

 res[1:4]
 #   N 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 id event
#1: 1 0 0 0 0 1 0 0 0 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1     0
#2: 2 0 0 0 0 0 0 1 0 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1     0
#3: 3 0 0 0 0 0 0 0 1 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1     0
#4: 4 0 0 0 0 0 0 0 0 1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1     0

注意:协变量没有显示在示例数据

数据

dfN <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
 1L, 1L, 
1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), 
week = c(5L, 7L, 8L, 9L, 10L, 11L, 14L, 15L, 16L, 17L, 18L, 
3L, 5L, 6L, 7L, 9L, 10L, 11L, 14L, 15L, 16L, 17L, 18L, 20L, 
22L)), .Names = c("id", "week"), row.names = c(NA, -25L), 
class = "data.frame")

答案 1 :(得分:1)

使用基数R:

> df$event<-0
> df[c(which(diff(df$id)!=0),nrow(df)),"event"]<-1
> df$time<-(unlist(sapply(split(df,df$id),function(d){ cumsum(c(1,diff(d$week))) })))
> df
   id week event time
1   1    5     0    1
2   1    7     0    3
3   1    8     0    4
4   1    9     0    5
5   1   10     0    6
6   1   11     0    7
7   1   14     0   10
8   1   15     0   11
9   1   16     0   12
10  1   17     0   13
11  1   18     1   14
12  2    3     0    1
13  2    5     0    3
14  2    6     0    4
15  2    7     0    5
16  2    9     0    7
17  2   10     0    8
18  2   11     0    9
19  2   14     0   12
20  2   15     0   13
21  2   16     0   14
22  2   17     0   15
23  2   18     0   16
24  2   20     0   18
25  2   22     1   20

或者如果你想采用拆分编辑改革的方式:

do.call(rbind,lapply(split(df,df$id),function(x){ 
    y<-cbind(x,event=0); y[nrow(x),ncol(x)+1]<-1; 
    z<-cbind(y,time=cumsum(c(1,diff(x$week)))); z }))

对于第三部分,如果您希望一直持续37周(对应于列&#39; d1&#39;到&#39; d37&#39;):

> result<-t(apply(df,1,function(x){ 
    tmp<-rep(0,37); names(tmp)<-paste0("d",1:37); 
    tmp[x["week"]]=1; c(x["id"],x["event"], tmp) }))
> result
      id event d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16 d17 d18
 [1,]  1     0  0  0  0  0  1  0  0  0  0   0   0   0   0   0   0   0   0   0
 [2,]  1     0  0  0  0  0  0  0  1  0  0   0   0   0   0   0   0   0   0   0
 [3,]  1     0  0  0  0  0  0  0  0  1  0   0   0   0   0   0   0   0   0   0
 [4,]  1     0  0  0  0  0  0  0  0  0  1   0   0   0   0   0   0   0   0   0 

       d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 d32 d33 d34 d35 d36
 [1,]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
 [2,]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
 [3,]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
 [4,]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

       d37
 [1,]   0
 [2,]   0
 [3,]   0
 [4,]   0