我有一个简单的数据帧:
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)
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)
由于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)
以下是几次尝试:
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)