如何为重复测量数据创建缺失值?

时间:2015-09-18 14:38:44

标签: r repeat missing-data

我有一个数据集,并不是每个主题的观察都在完全相同的时间点观察到,但是我想把它变成一个数据集,每个人的观察结果都是在完全相同的时间点观察到的(所以我可以在SAS proc traj中使用它。

例如,假设我有数据集“m”:

id   <- c(1,1,1,1,2,2,3,3,3)
age  <- c(2,3,4,5,3,6,2,5,8)
IQ   <- c(3,4,5,4,6,5,3,8,10)
m    <- data.frame(id,age,IQ)
> m
  id age IQ
1  1   2  3
2  1   3  4
3  1   4  5
4  1   5  4
5  2   3  6
6  2   6  5
7  3   2  3
8  3   5  8
9  3   8 10
> unique(age)
[1] 2 3 4 5 6 8

我想把m变成m2。但我只能手动完成。

id2   <- c(1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3)
age2  <- c(2,3,4,5,6,8,2,3,4,5,6,8,2,3,4,5,6,8) 
IQ2   <- c(3,4,5,4,NA,NA,6,5,NA,NA,NA,NA,3,8,10,NA,NA,NA) 
m2    <- data.frame(id2,age2,IQ2)    
m2
> m2
   id2 age2 IQ2
1    1    2   3
2    1    3   4
3    1    4   5
4    1    5   4
5    1    6  NA
6    1    8  NA
7    2    2   6
8    2    3   5
9    2    4  NA
10   2    5  NA
11   2    6  NA
12   2    8  NA
13   3    2   3
14   3    3   8
15   3    4  10
16   3    5  NA
17   3    6  NA
18   3    8  NA

有谁知道更聪明的方法吗?

2 个答案:

答案 0 :(得分:10)

使用tidyr,这是一个单线。您使用complete函数,该函数创建了传递给它的每个列组合的行,并使用NA填充其余行:

library(tidyr)
complete(m, id, age)

Source: local data frame [18 x 3]

      id   age    IQ
   (dbl) (dbl) (dbl)
1      1     2     3
2      1     3     4
3      1     4     5
4      1     5     4
5      1     6    NA
6      1     8    NA
7      2     2    NA
8      2     3     6
9      2     4    NA
10     2     5    NA
11     2     6     5
12     2     8    NA
13     3     2     3
14     3     3    NA
15     3     4    NA
16     3     5     8
17     3     6    NA
18     3     8    10

答案 1 :(得分:5)

我们可以使用data.table执行此操作。我们将data.frame转换为data.table(setDT(m)),设置关键列(setkey)并加入&{39; id&#的unique元素的交叉连接39;和&#39;年龄&#39;

library(data.table)
setkey(setDT(m), id, age)[CJ(unique(id), unique(age))]
#    id age IQ
# 1:  1   2  3
# 2:  1   3  4
# 3:  1   4  5
# 4:  1   5  4
# 5:  1   6 NA
# 6:  1   8 NA
# 7:  2   2 NA
# 8:  2   3  6
# 9:  2   4 NA
#10:  2   5 NA
#11:  2   6  5
#12:  2   8 NA
#13:  3   2  3
#14:  3   3 NA
#15:  3   4 NA
#16:  3   5  8
#17:  3   6 NA
#18:  3   8 10

在devel版本v1.9.5中,我们可以在unique=TRUE中使用CJ(来自@ Frank&#39;)

setDT(m, key=c('id', 'age'))[CJ(id, age, unique=TRUE)]

基准

set.seed(24)
m1 <- data.frame(id=rep(1:10000, each=10), age=sample(2:400, 10000*10, 
         replace=TRUE), IQ=rnorm(10000*10))
system.time(res1 <- complete(m1, id, age))
# user  system elapsed 
#18.888   0.000  16.258 


system.time({ DT <- as.data.table(m1)
         res2 <- setkey(DT, id, age)[CJ(unique(id), unique(age))]})
#  user  system elapsed 
#  0.000   0.000   0.279 



library(microbenchmark)
jeremy <- function() complete(m1, id, age)
akrun <- function() {DT <- as.data.table(m1)
   setkey(DT, id, age)[CJ(unique(id), unique(age))]}

microbenchmark(jeremy(), akrun(), times=20L, unit='relative')
#Unit: relative
#   expr      min       lq   mean   median       uq      max neval cld
#jeremy() 24.95042 30.84234 17.138 23.09175 12.16891 8.305394    20   b
# akrun()  1.00000  1.00000  1.000  1.00000  1.00000 1.000000    20  a