1

我有一个这样的数据框

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 . 我在寻找其他东西时确实在某个地方遇到了类似的请求,但现在找不到!

谢谢

4

5 回答 5

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
于 2013-07-18T16:30:28.237 回答
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.

于 2013-07-18T16:22:13.967 回答
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

通过:在 R 数据框中去重/折叠记录

于 2013-07-18T16:20:59.283 回答
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])
于 2015-07-14T19:25:56.973 回答
0

解决方案使用base

apply(test, 2, function(x) unique(na.omit(x)))
于 2016-02-22T22:23:00.687 回答