折叠行,其中一些都是NA,其他与一些NA不相交

时间:2015-01-20 01:22:51

标签: r aggregate na

我有一个简单的数据框:

ID    Col1    Col2    Col3    Col4
1     NA      NA      NA      NA  
1     5       10      NA      NA
1     NA      NA      15      20
2     NA      NA      NA      NA  
2     25      30      NA      NA
2     NA      NA      35      40 

我想重新格式化:

ID    Col1    Col2    Col3    Col4
1     5       10      15      20
2     25      30      35      40

(请注意:真实数据集有数千行,值来自生物数据 - NA不遵循简单模式,除了NA s是不相交的,是的每个ID只有3行。

第一步:删除只有NA个值的行。

表面上看起来很简单,但我遇到了一些问题。

complete.cases(DF)会返回所有FALSE,因此我无法使用此功能删除所有NA的行,如DF[complete.cases(DF),]中所示。这是因为所有行都包含至少一个NA

由于NA想要自己传播,因此使用is.na的其他方案由于同样的原因而失败。

第二步:将剩下的两行折叠成一行。

考虑使用像aggregate之类的东西来解决这个问题,但必须有一个比this更简单的方法,这根本不起作用。

感谢您的任何建议。

5 个答案:

答案 0 :(得分:16)

这是一种数据表方法,在列中使用na.omit(),按ID分组。

library(data.table)
setDT(df)[, lapply(.SD, na.omit), by = ID]
#    ID Col1 Col2 Col3 Col4
# 1:  1    5   10   15   20
# 2:  2   25   30   35   40

答案 1 :(得分:10)

尝试

library(dplyr)
DF %>% group_by(ID) %>% summarise_each(funs(sum(., na.rm = TRUE))) 

修改:要考虑一列中某个NAs的所有ID的情况,我们需要sum_NA()函数返回{{1}如果所有都是NA

NAs

答案 2 :(得分:6)

以下是几次合计尝试:

aggregate(. ~ ID, data=dat, FUN=na.omit, na.action="na.pass")
#  ID Col1 Col2 Col3 Col4
#1  1    5   10   15   20
#2  2   25   30   35   40

由于aggregate的公式接口默认在进行任何分组之前对整个数据使用na.omit,因此它会删除dat的每一行,因为它们都包含至少一个NA 1}}价值。试一试:nrow(na.omit(dat))返回0。因此,在这种情况下,请使用na.pass中的aggregate,然后使用na.omit来跳过通过的NA

或者,不要使用公式界面并指定要手动聚合的列:

aggregate(dat[-1], dat[1], FUN=na.omit )
aggregate(dat[c("Col1","Col2","Col3","Col4")], dat["ID"], FUN=na.omit)
#  ID Col1 Col2 Col3 Col4
#1  1    5   10   15   20
#2  2   25   30   35   40

答案 3 :(得分:1)

简单的方法是:

as.data.frame(lapply(myData[,c('Col1','Col2','Col3','Col4')],function(x)[!is.na(x)]))

但是如果不是所有列都具有相同数量的非NA值,那么您需要像这样修剪它们:

temp  <-  lapply(myData[,c('Col1','Col2','Col3','Col4')],function(x)x[!is.na(x)])
len  <-  min(sapply(temp,length))
as.data.frame(lapply(temp,`[`,seq(len)))

答案 4 :(得分:0)

dplyr 1.0.0起,您也可以(使用@Khashaa提供的数据):

df %>% 
 group_by(ID) %>%
 summarize(across(everything(), ~ first(na.omit(.))))

     ID  Col1  Col2  Col3  Col4
  <int> <int> <int> <int> <int>
1     1     5    10    15    20
2     2    NA    30    35    40