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

Mat*_*ien 11 aggregate r 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 
Run Code Online (Sandbox Code Playgroud)

我想重新格式化它:

ID    Col1    Col2    Col3    Col4
1     5       10      15      20
2     25      30      35      40
Run Code Online (Sandbox Code Playgroud)

(请注意:真实数据集有数千行,而值来自生物数据 - NA除了NAs是不相交的,s之后没有简单的模式,是的,每个行正好有3行ID).

第一步:摆脱只有NA值的行.

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

complete.cases(DF)返回all FALSE,所以我不能真正使用它来删除所有NAs 的行,如DF[complete.cases(DF),].这是因为所有行至少包含一行NA.

由于NAs想要传播自己,其他方案使用is.na失败的原因相同.

第二步:将剩余的两行折叠成一行.

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

谢谢你的建议.

Ric*_*ven 17

这是一个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
Run Code Online (Sandbox Code Playgroud)

  • `na.omit`很聪明.比"sum"更好,并且可以处理非数字数据.我谨慎地去编辑...... (4认同)

Kha*_*haa 11

尝试

library(dplyr)
DF %>% group_by(ID) %>% summarise_each(funs(sum(., na.rm = TRUE))) 
Run Code Online (Sandbox Code Playgroud)

编辑:为了说明一列具有NAs某一特定的所有情况的情况ID,我们需要sum_NA()函数,NA如果全部都是,则返回NAs

txt <- "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     NA      30      NA      NA
        2     NA      NA      35      40"
DF <- read.table(text = txt, header = TRUE)

# original code
DF %>% 
  group_by(ID) %>% 
  summarise_each(funs(sum(., na.rm = TRUE)))

# `summarise_each()` is deprecated.
# Use `summarise_all()`, `summarise_at()` or `summarise_if()` instead.
# To map `funs` over all variables, use `summarise_all()`
# A tibble: 2 x 5
     ID  Col1  Col2  Col3  Col4
  <int> <int> <int> <int> <int>
1     1     5    10    15    20
2     2     0    30    35    40

sum_NA <- function(x) {if (all(is.na(x))) x[NA_integer_] else sum(x, na.rm = TRUE)}

DF %>%
  group_by(ID) %>%
  summarise_all(funs(sum_NA))

DF %>%
  group_by(ID) %>%
  summarise_if(is.numeric, funs(sum_NA))

# A tibble: 2 x 5
     ID  Col1  Col2  Col3  Col4
  <int> <int> <int> <int> <int>
1     1     5    10    15    20
2     2    NA    30    35    40
Run Code Online (Sandbox Code Playgroud)


tmf*_*mnk 8

由于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
Run Code Online (Sandbox Code Playgroud)


the*_*ail 7

以下是几次尝试:

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
Run Code Online (Sandbox Code Playgroud)

由于aggregate默认情况下公式接口na.omit在进行任何分组之前使用整个数据,因此它将删除每一行,dat因为它们都包含至少一个NA值.试试吧:nrow(na.omit(dat))退货0.所以在这种情况下,使用na.passin aggregate然后na.omit跳过NA传递的s.

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

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
Run Code Online (Sandbox Code Playgroud)