【问题标题】:Remove columns with zero values from a dataframe从数据框中删除具有零值的列
【发布时间】:2014-02-27 02:31:05
【问题描述】:

我有一个data.frame:

SelectVar
     a   b  c   d   e   f   g   h   i j k l ll m n o p  q   r
1 Dxa8 Dxa8 0 Dxa8 Dxa8 0 Dxa8 Dxa8 0 0 0 0  0 0 0 0 0 Dxc8 0
2 Dxb8 Dxc8 0 Dxe8 Dxi8 0 tneg tpos 0 0 0 0  0 0 0 0 0 Dxi8 0

我想从数据框中删除两行中值为零的列,因此它会产生如下数据框:

SelectVar
     a   b    d    e    g   h     q   
1 Dxa8 Dxa8 Dxa8 Dxa8 Dxa8 Dxa8  Dxc8 
2 Dxb8 Dxc8 Dxe8 Dxi8 tneg tpos  Dxi8 

试过了:

SelectVar!=0

产生一个真/假数据框,并且:

SelectVar[, colSums(abs(SelectVar)) ! == 0]

这会产生错误。

如何删除每行中值为零的列?

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    你几乎拥有它。把这两个放在一起:

     SelectVar[, colSums(SelectVar != 0) > 0]
    

    这是有效的,因为因子列被评估为 >= 1 的数字。

    【讨论】:

    • 不,它不适用于NA 值。如果存在NA 值,请将测试替换为!is.na(colSums(SelectVar != 0)) & colSums(SelectVar != 0) > 0(或等效项)。
    • NA试试:SelectVar[, colSums(SelectVar != 0, na.rm = TRUE) > 0]
    • @MatthewLundberg - 这SelectVar[, colSums(SelectVar == 0) == 0] 会删除所有总和为零的列吗?
    • @M.Mashaye 这将在所有情况下返回相同的结果。 abs(x) == 0 等价于 x == 0
    • @TheGoat 这是问题中data.frame 的名称。
    【解决方案2】:

    一个 dplyr 友好的解决方案:

    SelectVar %>% select_if(colSums(.) != 0)

    【讨论】:

    • 但是如果有负值并且负数和正数加起来为0怎么办?你会用这种方法删除那些列,对吧?
    • 好消息@charlesdarwin!很可能,是的。虽然我最近发现了另一个对 dplyr/tidyverse 友好的解决方案 purrr::discard(~all(is.na(.)))
    【解决方案3】:

    也试试

    SelectVar[, !apply(SelectVar == 0, 2, all)]
    

    这是从这里拍摄的:

    Delete all columns with 0 from matrix

    【讨论】:

    • 这可能会更慢,尤其是在较大的数据集上。另外,我认为 OP 正在寻找any 而不是all
    • 也许,我只是复制粘贴帖子。它似乎工作正常。
    【解决方案4】:

    dplyr 1.0.0 之后的一个选项可能是:

    df %>%
     select(where(~ any(. != 0)))
    
         a    b    d    e    g    h    q
    1 Dxa8 Dxa8 Dxa8 Dxa8 Dxa8 Dxa8 Dxc8
    2 Dxb8 Dxc8 Dxe8 Dxi8 tneg tpos Dxi8
    

    【讨论】:

      【解决方案5】:

      较快的选项(根据平均执行时间缩短约 40%)是

      df[,-(which(colSums(df)==0))]

      我们可以使用由 3,000 列和两个观察值组成的简单示例数据框来对这两个选项进行基准测试。

      # Create simply 2 X 3000 data frame with many 1s and 0s
      # 500 columns have all 0s
      df = matrix(c(rep(c(0,1,1),1000),rep(c(1,0,0),1000)),nrow=2)
      df = as.data.frame(df)
      
      # Benchmark the two options in milliseconds, 100 times
      library(microbenchmark)
      microbenchmark(
        df[,colSums(df != 0) > 0],
        df[,-(which(colSums(df)==0))]
        )
      
      Unit: milliseconds
                                   expr     min       lq     mean   median       uq      max neval
             df[, colSums(df != 0) > 0] 23.3844 24.77905 30.24852 26.37730 29.17175 140.6486   100
       df[, -(which(colSums(df) == 0))] 17.3664 19.12815 21.58901 20.59055 22.29905  41.9485   100
      
      

      【讨论】:

        【解决方案6】:

        删除任何零列的简单答案:

        columns_to_keep = (colSums(SelectVar != 0) == nrow(SelectVar))
        NewTable = SelectVar[, columns_to_keep]
        

        【讨论】:

        • 你的意思是SelectVar[, columns_to_keep]?为了技术上正确,您可以使用colSums(SelectVar != 0),使用!= 而不是>,以防出现负数。
        • 我更正了答案,谢谢!
        • 我想现在已经完成了,对不起我是新用户。
        【解决方案7】:

        要删除所有仅包含零的列,只需将数据框传递给以下函数:

        remove_zero_cols <- function(df) {
          rem_vec <- NULL
          for(i in 1:ncol(df)){
            this_sum <- summary(df[,i])
            zero_test <- length(which(this_sum == 0))
            if(zero_test == 6) {
              rem_vec[i] <- names(df)[i]
            }
          }
          features_to_remove <- rem_vec[!is.na(rem_vec)]
          rem_ind <- which(names(df) %in% features_to_remove)
          df <- df[,-rem_ind]
          return(df)
        }
        

        例子:

        iris$Sepal.Width <- 0
        new_df <- remove_zero_cols(iris)
        print(new_df)
        

        【讨论】:

        • if(zero_test == 6) 中的 6 是多少
        • 第 4 行的汇总函数给出了 6 个列的汇总。如果所有 6 个值都是 0,则该列包含所有零,因此被删除。
        【解决方案8】:

        你可以试试

           [row, column] = SelectVar.shape
            for j in range(column):
               if np.all(SelectVar.iloc[:, j] == 0):
                   SelectVar = SelectVar.drop(SelectVar.columns[j], axis=1, inplace=True)
        

        【讨论】:

          【解决方案9】:

          迟到的答案,但可以在这里工作的另一种基本 R 方法是断言每列中的最小值或最大值为零:

          colMax <- sapply(SelectVar, max, na.rm=TRUE)
          colMin <- sapply(SelectVar, min, na.rm=TRUE)
          SelectVar[, colMin != 0 | colMax != 0]
          

          【讨论】:

            【解决方案10】:

            以上所有答案均有效 -
            但对于我们中的一些人来说,遵循目标remove columns with zero values 阅读的最直观的解决方案可能是:

            df %>% select(where(~ sum(.) != 0))
            

            你可以读成:
            For every column (~), remove it (!=) if its sum (sum(.)) is zero

            【讨论】:

              猜你喜欢
              • 2023-03-22
              • 2012-01-13
              • 1970-01-01
              • 1970-01-01
              • 2018-09-21
              • 2021-08-23
              • 1970-01-01
              • 1970-01-01
              • 2021-06-18
              相关资源
              最近更新 更多