0

我有一个数据框,我想重塑它,以便每个观察只有一行obs。这是示例数据:

data <- data.frame("obs" = c('1','1','1','2','2'),
                   "value1" = c(1,NA,NA,NA,NA),
                   "value2" = c(NA,NA,3,1,NA),
                   "value3" = c(NA,2,NA,NA,5))

数据如下所示:

  obs value1 value2 value3
   1      1     NA     NA
   1     NA     NA      2
   1     NA      3     NA
   2     NA      1     NA
   2     NA     NA      5

我想把它改造成:

obs  value1  value2  value3
1       1      3       2
2       NA     1       5

谢谢!

4

3 回答 3

4
library(data.table)
dt = data.table(dat)

dt[, lapply(.SD, function(x) x[!is.na(x)]), by = obs]

如果给定观察的每个值有多个条目,这将使用 R 的回收逻辑来填充其余部分。

于 2013-06-19T18:45:51.167 回答
2

我就是这样做的,使用plyr

foo <- function(x){
    if (all(is.na(x))) return(NA)
    else return(x[!is.na(x)])
}

ddply(dat,.(obs),colwise(foo))

这当然假设您确实在每列中对于obs.

如果不是这种情况,并且您想取多个值的平均值,则可以尝试按照 Justin 的建议进行操作:

mean(x[!is.na(x)])
于 2013-06-19T18:36:44.520 回答
2

基础解决方案:

out <- lapply(split(data, data$obs), function(x) {
    ans <- lapply(x[, -1], na.omit)
    data.frame(obs = x[1, 1], t(sapply(ans, "[", 1)))
})

do.call(rbind, out)

## > do.call(rbind, out)
##   obs value1 value2 value3
## 1   1      1      3      2
## 2   2     NA      1      5
于 2013-06-19T18:51:58.690 回答