在不同列中压缩具有NA的行以创建单个行

时间:2013-07-18 16:02:01

标签: r dataframe plyr

我有一个像这样的数据框

test <- data.frame(id = rep(LETTERS[1:2],each = 3), 
    a = c(1,NA,NA,10,NA,NA), 
    b = c(2,NA,NA,20,NA,NA), 
    c = c(NA,3,NA,NA,30,NA), 
    d = c(NA,NA,4,NA,NA,40))

我得到了这个数据帧,并希望将其转换为每个唯一的'id'只有一行,而数据帧中没有NA。

我这样做

ddply(test, 
    .variables = 'id', 
    .fun = function(df){
        colSums(df[,1:4], na.rm = T)})

获取此data.frame

      id  a  b  c  d
    1  A  1  2  3  4
    2  B 10 20 30 40

它有效,但是有一种更直接的方法可以不使用colSums,有点压缩行为每个'id'创建一行,因为在每个'id'中,所有列都有只有一个值,其余是NA。我确实遇到了类似的请求,同时寻找其他东西,但现在找不到它!

由于

5 个答案:

答案 0 :(得分:5)

使用R基本功能

> test[is.na(test)] <-0
> aggregate(.~id, data=test, FUN="sum")
  id  a  b  c  d
1  A  1  2  3  4
2  B 10 20 30 40

答案 1 :(得分:1)

这是一个解决方案,当我遇到类似的问题时,建议我使用data.table和is.na:

require(data.table)
DT=data.table(test)

unique(DT[, lapply(.SD, function(x) x[!is.na(x)]), by = id])

   id  a  b  c  d
1:  A  1  2  3  4
2:  B 10 20 30 40

请注意,这会为您提供data.table,而不是data.frame。如果您不熟悉这种数据结构,可以轻松转换它:

data.frame(unique(DT[, lapply(.SD, function(x) x[!is.na(x)]), by = id]))

  id  a  b  c  d
1  A  1  2  3  4
2  B 10 20 30 40

via:Deduplicating/collapsing records in an R dataframe

答案 2 :(得分:1)

我不知道这更容易,但是:

test <- data.frame(id.l = rep(LETTERS[1:2],each = 3), 
                   a = c(1,NA,NA,10,NA,NA), 
                   b = c(2,NA,NA,20,NA,NA), 
                   c = c(NA,3,NA,NA,30,NA), 
                   d = c(NA,NA,4,NA,NA,40))
x <- melt(test, id.l = id, na.rm = T)
dcast(x, id.l ~ variable)
# id.l  a  b  c  d
# 1    A  1  2  3  4
# 2    B 10 20 30 40

我不得不更改您的ID列的名称,因为我无法生成id = id

答案 3 :(得分:1)

另一个dplyr解决方案如下:

library(dplyr)
test %>% group_by(id) %>% summarise(a = na.omit(a)[1], b = na.omit(b)[1],
c = na.omit(c)[1], d = na.omit(d)[1])

答案 4 :(得分:0)

使用base

的解决方案
apply(test, 2, function(x) unique(na.omit(x)))