R 如何删除仅包含NAs的列?

R 如何删除仅包含NAs的列?,r,dataframe,na,R,Dataframe,Na,我有一个data.frame,其中包含一些包含所有NA值的列,如何从data.frame中删除它们 我可以使用这个功能吗 na.omit(...) 指定一些附加参数?似乎您只想删除中包含ALLNAs的列,而保留包含NAs的某些行的列。我会这样做(但我相信有一个有效的矢量化解决方案: #set seed for reproducibility set.seed <- 103 df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , v

我有一个data.frame,其中包含一些包含所有NA值的列,如何从data.frame中删除它们

我可以使用这个功能吗

na.omit(...) 

指定一些附加参数?

似乎您只想删除中包含ALL
NA
s的列,而保留包含
NA
s的某些行的列。我会这样做(但我相信有一个有效的矢量化解决方案:

#set seed for reproducibility
set.seed <- 103
df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , vals = sample( c( 1:3 , NA ) , 10 , repl = TRUE ) )
df
#      id nas vals
#   1   1  NA   NA
#   2   2  NA    2
#   3   3  NA    1
#   4   4  NA    2
#   5   5  NA    2
#   6   6  NA    3
#   7   7  NA    2
#   8   8  NA    3
#   9   9  NA    3
#   10 10  NA    2

#Use this command to remove columns that are entirely NA values, it will leave columns where only some values are NA
df[ , ! apply( df , 2 , function(x) all(is.na(x)) ) ]
#      id vals
#   1   1   NA
#   2   2    2
#   3   3    1
#   4   4    2
#   5   5    2
#   6   6    3
#   7   7    2
#   8   8    3
#   9   9    3
#   10 10    2
#为再现性设定种子
set.seed一种方法:

df[, colSums(is.na(df)) != nrow(df)]
如果列中的NAs计数等于行数,则必须完全为NA

或者类似地

df[colSums(!is.na(df)) > 0]

另一个带有
过滤器的选项

Filter(function(x) !all(is.na(x)), df)

注:数据来自@Simon O'Hanlon的帖子。

另一个选项是
看门人
软件包:

df <- remove_empty_cols(df)

df这里有一个dplyr解决方案:

df %>% select_if(~sum(!is.na(.)) > 0)
更新:
dplyr 1.0
起,
summary_if()
函数被取代。以下是使用
where()
tidyselect函数的两个其他解决方案:

df %>% 
  select(
    where(
      ~sum(!is.na(.x)) > 0
    )
  )

一个直观的脚本:
dplyr::select_if(~!all(is.na()))
。它实际上只保留缺少列的所有元素(删除缺少列的所有元素)

>df%>%scape()
意见:10
变量:3
$ID1,2,3,4,5,6,7,8,9,10
$nas不,不,不,不,不,不,不,不,不,不,不,不
$vals NA,1,1,NA,1,1,1,1,2,3,NA
>df%>%如果(~!all(is.na)())选择
id VAL
11NA
2   2    1
3   3    1
4不适用
5   5    1
6   6    1
7   7    1
8   8    2
9   9    3
10 NA

因为性能对我来说非常重要,所以我对上述所有功能进行了基准测试

注:数据来自@Simon O'Hanlon的帖子。仅尺寸为15000而非10

library(tidyverse)
library(microbenchmark)

set.seed(123)
df <- data.frame(id = 1:15000,
                 nas = rep(NA, 15000), 
                 vals = sample(c(1:3, NA), 15000,
                               repl = TRUE))
df

MadSconeF1 <- function(x) x[, colSums(is.na(x)) != nrow(x)]

MadSconeF2 <- function(x) x[colSums(!is.na(x)) > 0]

BradCannell <- function(x) x %>% select_if(~sum(!is.na(.)) > 0)

SimonOHanlon <- function(x) x[ , !apply(x, 2 ,function(y) all(is.na(y)))]

jsta <- function(x) janitor::remove_empty(x)

SiboJiang <- function(x) x %>% dplyr::select_if(~!all(is.na(.)))

akrun <- function(x) Filter(function(y) !all(is.na(y)), x)

mbm <- microbenchmark(
  "MadSconeF1" = {MadSconeF1(df)},
  "MadSconeF2" = {MadSconeF2(df)},
  "BradCannell" = {BradCannell(df)},
  "SimonOHanlon" = {SimonOHanlon(df)},
  "SiboJiang" = {SiboJiang(df)},
  "jsta" = {jsta(df)}, 
  "akrun" = {akrun(df)},
  times = 1000)

mbm



您好!请使您的帖子具有可复制性。阅读有关如何执行此操作的帖子。谢谢。此帖子是否有帮助?您能否发布
标题(数据)
?是否要删除相应的列或行?@e4f4我要删除相应的列(我要删除的列的所有值均为NA)data.frame的可能副本有两种类型的列:一种是所有值都是数字的列,另一种是所有值都是NASo的列。这将起作用。它只删除所有值都是
NA
。很好的解决方案。我会做
应用(is.NA(df),1,all)
,尽管只是因为它稍微整洁一点,而且
is.NA()
用于所有
df
而不是一次一行(显示速度要快一点)。@MadScone好提示-看起来更整洁。但你应该跨列应用,而不是跨行应用。@MadScone编辑在注释5分钟后被锁定。我不必担心,这没什么大不了的!!:-)我如何删除阈值大于NA的列?或者以百分比(比如说50%以上)为单位?@LoveDyna可能最好提交一个单独的问题,假设你在发表评论后还没有提出过这个问题。但无论如何,您可以始终执行类似于
df[,colSums(is.na(df))
的操作,即只保留至少50%非空白的列。使用相关矩阵的人员必须使用
df[,colSums(is.na(df))!=nrow(df)-1]
,因为对角线总是
1
可以将其用于dplyr(版本0.5.0)同时选择_if函数
df%>%select_if(colSums(!is.na(.))>0)
@MadScone它在“,”处给我语法错误,对于df[,colSums(is.na(df))!=nrow(df)],在df[colSums(!is.na(df))>0]中的“!”处给我语法错误。我是否在~15k行和~5k列中遗漏了一些内容,这真的需要花费很长时间。@EngrStudent接受答案的解决方案是否更快?已经好几年了。我不记得了。DJV下面有一个很好的计时帖子。
janitor::remove\u empty\u cols()
不推荐使用-use
df有时第一次迭代是JIT编译的,所以它的时间非常差,也不是很有特点。我认为更大的样本量对分布的右尾所做的事情很有趣。这是一个很好的工作。我再次运行它,不确定我是否改变了情节。关于分配,确实如此。当我有时间的时候,我可能应该比较不同的样本量。如果你对其中一种趋势进行qplot(),比如“akrun”,那么我打赌有一点与其他的分布非常不同。其余部分表示重复运行所需的时间,但这表示运行一次所需的时间。有句老话:你可以有20年的经验,也可以只有一年的经验20次。非常好!我很惊讶有几个样品处于极端的尾部。我想知道为什么这些要贵得多。JIT可能是1或2,但不是20。条件打断?其他的?再次感谢您的更新。不客气,谢谢您的想法。不知道,我实际上允许它“自由”运行。
> df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , vals = sample( c( 1:3 , NA ) , 10 , repl = TRUE ) )

> df %>% glimpse()
Observations: 10
Variables: 3
$ id   <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
$ nas  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
$ vals <int> NA, 1, 1, NA, 1, 1, 1, 2, 3, NA

> df %>% select_if(~!all(is.na(.))) 
   id vals
1   1   NA
2   2    1
3   3    1
4   4   NA
5   5    1
6   6    1
7   7    1
8   8    2
9   9    3
10 10   NA
library(tidyverse)
library(microbenchmark)

set.seed(123)
df <- data.frame(id = 1:15000,
                 nas = rep(NA, 15000), 
                 vals = sample(c(1:3, NA), 15000,
                               repl = TRUE))
df

MadSconeF1 <- function(x) x[, colSums(is.na(x)) != nrow(x)]

MadSconeF2 <- function(x) x[colSums(!is.na(x)) > 0]

BradCannell <- function(x) x %>% select_if(~sum(!is.na(.)) > 0)

SimonOHanlon <- function(x) x[ , !apply(x, 2 ,function(y) all(is.na(y)))]

jsta <- function(x) janitor::remove_empty(x)

SiboJiang <- function(x) x %>% dplyr::select_if(~!all(is.na(.)))

akrun <- function(x) Filter(function(y) !all(is.na(y)), x)

mbm <- microbenchmark(
  "MadSconeF1" = {MadSconeF1(df)},
  "MadSconeF2" = {MadSconeF2(df)},
  "BradCannell" = {BradCannell(df)},
  "SimonOHanlon" = {SimonOHanlon(df)},
  "SiboJiang" = {SiboJiang(df)},
  "jsta" = {jsta(df)}, 
  "akrun" = {akrun(df)},
  times = 1000)

mbm
Unit: microseconds
         expr    min      lq      mean  median      uq      max neval  cld
   MadSconeF1  154.5  178.35  257.9396  196.05  219.25   5001.0  1000 a   
   MadSconeF2  180.4  209.75  281.2541  226.40  251.05   6322.1  1000 a   
  BradCannell 2579.4 2884.90 3330.3700 3059.45 3379.30  33667.3  1000    d
 SimonOHanlon  511.0  565.00  943.3089  586.45  623.65 210338.4  1000  b  
    SiboJiang 2558.1 2853.05 3377.6702 3010.30 3310.00  89718.0  1000    d
         jsta 1544.8 1652.45 2031.5065 1706.05 1872.65  11594.9  1000   c 
        akrun   93.8  111.60  139.9482  121.90  135.45   3851.2  1000 a


autoplot(mbm)
mbm %>% 
  tbl_df() %>%
  ggplot(aes(sample = time)) + 
  stat_qq() + 
  stat_qq_line() +
  facet_wrap(~expr, scales = "free")