代码之家  ›  专栏  ›  技术社区  ›  Gnark

从数据框中删除所有值为NA的列

  •  103
  • Gnark  · 技术社区  · 15 年前

    我在数据帧方面遇到了问题,无法亲自解决该问题:
    这个 数据文件 具有任意性 属性为列 每行 代表一 数据集 .

    问题是:
    如何 删除列的位置 所有 行值为na ?

    7 回复  |  直到 7 年前
        1
  •  121
  •   teucer    15 年前

    试试这个:

    df <- df[,colSums(is.na(df))<nrow(df)]
    
        2
  •  77
  •   mnel    13 年前

    迄今为止提供的两种方法都失败了,因为它们创建了大量的数据集(除了其他内存问题)。 is.na(df) ,该对象的大小与 df .

    以下是两种更节省内存和时间的方法

    一种使用 Filter

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

    以及使用data.table的方法(用于一般的时间和内存效率)

    library(data.table)
    DT <- as.data.table(df)
    DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]
    

    使用大数据的示例(30列,1E6行)

    big_data <- replicate(10, data.frame(rep(NA, 1e6), sample(c(1:8,NA),1e6,T), sample(250,1e6,T)),simplify=F)
    bd <- do.call(data.frame,big_data)
    names(bd) <- paste0('X',seq_len(30))
    DT <- as.data.table(bd)
    
    system.time({df1 <- bd[,colSums(is.na(bd) < nrow(bd))]})
    # error -- can't allocate vector of size ...
    system.time({df2 <- bd[, !apply(is.na(bd), 2, all)]})
    # error -- can't allocate vector of size ...
    system.time({df3 <- Filter(function(x)!all(is.na(x)), bd)})
    ## user  system elapsed 
    ## 0.26    0.03    0.29 
    system.time({DT1 <- DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]})
    ## user  system elapsed 
    ## 0.14    0.03    0.18 
    
        3
  •  16
  •   zack    7 年前

    dplyr 现在有一个 select_if 此处可能有用的动词:

    library(dplyr)
    temp <- data.frame(x = 1:5, y = c(1,2,NA,4, 5), z = rep(NA, 5))
    not_all_na <- function(x) any(!is.na(x))
    not_any_na <- function(x) all(!is.na(x))
    
    > temp
      x  y  z
    1 1  1 NA
    2 2  2 NA
    3 3 NA NA
    4 4  4 NA
    5 5  5 NA
    
    > temp %>% select_if(not_all_na)
      x  y
    1 1  1
    2 2  2
    3 3 NA
    4 4  4
    5 5  5
    
    > temp %>% select_if(not_any_na)
      x
    1 1
    2 2
    3 3
    4 4
    5 5
    
        4
  •  14
  •   mropa    15 年前

    另一种方法是使用 apply() 功能。

    如果您有data.frame

    df <- data.frame (var1 = c(1:7,NA),
                      var2 = c(1,2,1,3,4,NA,NA,9),
                      var3 = c(NA)
                      )
    

    然后你可以用 应用程序() 查看哪些列满足您的条件,这样您就可以简单地执行与musa答案中相同的子集,只需使用 apply 方法。

    > !apply (is.na(df), 2, all)
     var1  var2  var3 
     TRUE  TRUE FALSE 
    
    > df[, !apply(is.na(df), 2, all)]
      var1 var2
    1    1    1
    2    2    2
    3    3    1
    4    4    3
    5    5    4
    6    6   NA
    7    7   NA
    8   NA    9
    
        5
  •  5
  •   jpmorris    8 年前
    df[sapply(df, function(x) all(is.na(x)))] <- NULL
    
        6
  •  1
  •   Luis M. Nieves    10 年前

    我希望这也能有所帮助。它可以做成一个命令,但我发现把它分成两个命令,这样读起来更容易。我按照下面的说明做了一个函数,并以闪电般的速度工作。

    naColsRemoval = function (DataTable) { na.cols = DataTable [ , .( which ( apply ( is.na ( .SD ) , 2 , all ) ) )] DataTable [ , unlist (na.cols) := NULL , with = F] }

    .sd将允许将验证限制在表的一部分(如果您愿意),但它将把整个表作为

        7
  •  0
  •   jeromeResearch    7 年前

    接受的答案不适用于非数字列。从 this answer ,以下内容适用于包含不同数据类型的列

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