rbind 数据帧与 survival::Surv 个对象

rbind dataframes with survival::Surv objects

如何合并包含 survival::Surv 对象的两个数据帧,以便生成的数据帧中的字段与源数据帧具有相同的 class?

我发现使用 rbind 会导致 Surv 对象被转换为矩阵。比如我创建了df1如下:

library(survival)
df1 <- data.frame(obs = c('A','B','C','D','E')
                  , lo = c(10,20,30,40,50)
                  , hi = c(30,30,30,40,50))
df1$conc <-survival::Surv(df1$lo, df1$hi, type = "interval2")

接下来,我检查 df1 的内容和结构以及 df1$conc class。请注意,在 str 命令中, concSurv

> df1
  obs lo hi     conc
1   A 10 30 [10, 30]
2   B 20 30 [20, 30]
3   C 30 30       30
4   D 40 40       40
5   E 50 50       50

> str(df1)    
'data.frame':   5 obs. of  4 variables:
 $ obs : chr  "A" "B" "C" "D" ...
 $ lo  : num  10 20 30 40 50
 $ hi  : num  30 30 30 40 50
 $ conc: 'Surv' num [1:5, 1:3] [10, 30] [20, 30] 30       40       ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : NULL
  .. ..$ : chr [1:3] "time1" "time2" "status"
  ..- attr(*, "type")= chr "interval"

> class(df1$conc)
[1] "Surv"

接下来,创建 df2 作为 df1 的副本,rbind df1df2 一起作为 df3

df2 <- df1
df3 <- rbind(df1,df2)

df3 的结构看起来与上面的 df1 几乎相同,但是字段 conc 是数字并且缺少 type 属性。

>str(df3)
'data.frame':   10 obs. of  4 variables:
 $ obs : chr  "A" "B" "C" "D" ...
 $ lo  : num  10 20 30 40 50 10 20 30 40 50
 $ hi  : num  30 30 30 40 50 30 30 30 40 50
 $ conc: num [1:10, 1:3] 10 20 30 40 50 10 20 30 40 50 ...
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : NULL
  .. ..$ : chr [1:3] "time1" "time2" "status"

另请注意 df3$conc 的 class 不是 Surv 对象

>class(df3$conc)
[1] "matrix" "array" 

df3 的内容看起来有点奇怪,但考虑到 survival 包存储其数据的方式是有道理的。

> df3
   obs lo hi conc.time1 conc.time2 conc.status
1    A 10 30         10         30           3
2    B 20 30         20         30           3
3    C 30 30         30          1           1
4    D 40 40         40          1           1
5    E 50 50         50          1           1
6    A 10 30         10         30           3
7    B 20 30         20         30           3
8    C 30 30         30          1           1
9    D 40 40         40          1           1
10   E 50 50         50          1           1

我们可以使用bind_rows

library(dplyr)
df3 <- bind_rows(df1, df2)

df3
#   obs lo hi     conc
#1    A 10 30 [10, 30]
#2    B 20 30 [20, 30]
#3    C 30 30       30
#4    D 40 40       40
#5    E 50 50       50
#6    A 10 30 [10, 30]
#7    B 20 30 [20, 30]
#8    C 30 30       30
#9    D 40 40       40
#10   E 50 50       50

如果我们需要使用 rbind,对普通列进行子集化(conc 是一个 matrix),然后分配串联的 'conc'

nm1 <- setdiff(names(df1), 'conc')
df3 <- rbind(df1[nm1], df2[nm1])
df3$conc <- c(df1$conc, df2$conc)
df3
#   obs lo hi     conc
#1    A 10 30 [10, 30]
#2    B 20 30 [20, 30]
#3    C 30 30       30
#4    D 40 40       40
#5    E 50 50       50
#6    A 10 30 [10, 30]
#7    B 20 30 [20, 30]
#8    C 30 30       30
#9    D 40 40       40
#10   E 50 50       50