移动NA的底部
问题描述:
我在寻找一个简单的方法来与至少一个NA将所有行数据帧/ DataTable的底部。例如:移动NA的底部
> df <- data.table(aaa=c(1,2,3,4,NA,6,7),
bbb=c(1,9,5,NA,3,NA,9),
ccc=c(NA,3,NA,4,8,NA,2)
)
> df
aaa bbb ccc
1: 1 1 NA
2: 2 9 3
3: 3 5 NA
4: 4 NA 4
5: NA 3 8
6: 6 NA NA
7: 7 9 2
会变成这样的事情:
> df2 <- moveNAtoBottom(df)
> df2
aaa bbb ccc
1: 2 9 3
2: 7 9 2
3: 1 1 NA
4: 3 5 NA
5: 4 NA 4
6: NA 3 8
7: 6 NA NA
即顶部没有NA的所有列。
注:
- 现在,我真的不关心,如果应用有任何排序的行,或者如果为了保持或逆转......只要表现有两个部分,上面一个没有来港,下一个为NAS
- 这可以在dataframes或数据表
- 依赖是正常
更妙的是,如果我能能够在指定列哪个搜索NA必须被应用。例如,仍与前面的例子:
> df3 <- moveNAtoBottom(df, applyTo = c("bbb", "ccc"))
> df3
aaa bbb ccc
1: 2 9 3
2: NA 3 8
3: 7 9 2
4: 1 1 NA
5: 3 5 NA
6: 4 NA 4
7: 6 NA NA
感谢
答
一个简单的基础R解决方案是:
> df <- data.frame(aaa=c(1,2,3,4,NA,6,7),
+ bbb=c(1,9,5,NA,3,NA,9),
+ ccc=c(NA,3,NA,4,8,NA,2))
> ok <- complete.cases(df)
> rbind(df[ok,], df[!ok,])
aaa bbb ccc
2 2 9 3
7 7 9 2
1 1 1 NA
3 3 5 NA
4 4 NA 4
5 NA 3 8
6 6 NA NA
而且只选择一些列:
> ok <- complete.cases(df[, c("bbb","ccc")])
> rbind(df[ok,], df[!ok,])
aaa bbb ccc
2 2 9 3
5 NA 3 8
7 7 9 2
1 1 1 NA
3 3 5 NA
4 4 NA 4
6 6 NA NA
答
尝试:
na=apply(df,1,function(x)sum(is.na(x)))
df[order(na),]
或函数
moveNAtoBottom<-function(df, applyTo=NULL){
df<-as.data.frame(df)
if (is.null(applyTo)) applyTo=colnames(df)
na=rowSums(is.na(df[,applyTo,drop=F]))
data.table(df[order(na),])
}
moveNAtoBottom(df)
moveNAtoBottom(df,c("ccc", "aaa"))
aaa bbb ccc
1: 2 9 3
2: 4 NA 4
3: 7 9 2
4: 1 1 NA
5: 3 5 NA
6: NA 3 8
7: 6 NA NA
答
你可以这样做:
library(dplyr)
df %>%
arrange(rowSums(is.na(.)))
其中给出:
# aaa bbb ccc
#1 2 9 3
#2 7 9 2
#3 1 1 NA
#4 3 5 NA
#5 4 NA 4
#6 NA 3 8
#7 6 NA NA
还是应该要指定列名:
df %>%
arrange(rowSums(is.na(select_(., 'bbb:ccc'))))
其中给出:
# aaa bbb ccc
#1 2 9 3
#2 NA 3 8
#3 7 9 2
#4 1 1 NA
#5 3 5 NA
#6 4 NA 4
#7 6 NA NA
答
由于OP使用data.table
,与data.table
一个选项循环通过与lapply
列,检查它是否是NA(is.na
),获得该行逐行总和与Reduce
,并用它来order
“DF”的行。
df[order(Reduce(`+`, lapply(df, is.na)))]
# aaa bbb ccc
#1: 2 9 3
#2: 7 9 2
#3: 1 1 NA
#4: 3 5 NA
#5: 4 NA 4
#6: NA 3 8
#7: 6 NA NA
这里还有一个类似的方法:
df[, anyna := FALSE]
for (k in names(df)) df[!(anyna), anyna := is.na(get(k))]
df[order(anyna)][, anyna := NULL][]
效果很好, 谢谢。我能问一个关于'dplyr'问题?为什么它与管道的工作,但并非没有?如果他们以同样的方式为'magrittr'的管道工程,人们会认为'安排(rowSums(是。na(select_(df,'bbb:ccc'))))'也可以,不是吗? –
你需要指定你想要在哪个'data'上执行'arrange()':尝试'arrange(df,rowSums(is.na(select_(df,'bbb:ccc'))))' –
哦,当然,我明白,谢谢。 –