R 折叠行,其中一些行全部为NA,其他行与某些NAs不相交
我有一个简单的数据框架:R 折叠行,其中一些行全部为NA,其他行与某些NAs不相交,r,aggregate,na,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 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
s不遵循简单模式,除了NA
s是不相交的,每个ID
正好有3行)
第一步:删除只有NA
值的行
表面上看这很简单,但我遇到了一些问题
complete.cases(DF)
返回allFALSE
,因此我不能像在DF[complete.cases(DF),]
中那样用它来删除所有NA
s的行。这是因为所有行至少包含一个NA
由于NA
s想要自我传播,因此使用is.NA
的其他方案也因同样的原因失败
第二步:将其余两行折叠为一行
考虑使用aggregate
之类的方法来实现这一点,但必须有一种比这更简单的方法,它根本不起作用
谢谢你的建议。简单的方法是:
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)))
temp以下是一些聚合尝试:
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。在进行任何分组之前,忽略整个数据,它将删除dat
的每一行,因为它们都至少包含一个na
值。试试看:nrow(na.omit(dat))
返回0
。因此,在这种情况下,在aggregate
中使用na.pass
,然后使用na.ommit
跳过通过的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
试一试
编辑:为了说明某个ID
的一列包含所有NAs
的情况,我们需要sum\u 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
txt%
总结每一项(funs(sum(,na.rm=TRUE)))
#“summary_each()”已弃用。
#改为使用'summary_all()'、'summary_at()'或'summary_if()'。
#要在所有变量上映射'funs',请使用'summary_all()`
#一个tibble:2x5
ID Col1 Col2 Col3 Col4
1 1 5 10 15 20
2 2 0 30 35 40
总额%
分组依据(ID)%>%
总结所有(funs(sum_NA))
DF%>%
分组依据(ID)%>%
总结如果(是数字,funs(总和))
#一个tibble:2x5
ID Col1 Col2 Col3 Col4
1 1 5 10 15 20
2 2 NA 30 35 40
这是一种数据表方法,它在列之间使用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
由于dplyr 1.0.0
,您还可以(使用@Khashaa提供的数据):
df%>%
分组依据(ID)%>%
总结(跨越所有内容(),~first(na.省略())
ID Col1 Col2 Col3 Col4
1 1 5 10 15 20
2 2 NA 30 35 40
数据总是100%数字吗?相关:每个组的每列中总是有一个非NA值,还是会有更多?更多!无论好坏,省略是聪明的。优于sum
,适用于非数字数据。我将谨慎地编辑…如果任何列都有某个ID的所有NAs,则此解决方案不起作用。我认为对每个列进行总结(funs(na.omit(.))
也有效是,但我认为,如果任何一列有两个以上的非NA观测值,那么这将产生一个稍微不协调的结果。如果任何一列在某个ID
上都有NA
s,那么这个解决方案就不起作用。例如,将Col1
中的ID=2
替换为NA
。而funs(na.omit(.))
将抛出错误error:列Col1必须是长度1(摘要值),而不是0
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
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