【问题标题】:How to delete R data.frame columns with only zero values? [duplicate]如何删除只有零值的 R data.frame 列? [复制]
【发布时间】:2020-08-27 17:26:28
【问题描述】:

类似于Deleting column with zero values in R?

样本数据

a <- c(0,2,5,7,2,3,0,3)
b <- c(2,3,0,0,1,0,4,0)
c <- c(0,0,0,0,0,0,0,0)
d <- c(2,5,1,2,3,4,5,6)

df <- data.frame(a,b,c,d)

但我只想获得一个以 a、b、d 为列的 data.frame

【问题讨论】:

    标签: r


    【解决方案1】:

    使用dplyr 的一个选项可能是:

    df %>%
     select(where(~ any(. != 0)))
    
    1 0 2 2
    2 2 3 5
    3 5 0 1
    4 7 0 2
    5 2 1 3
    6 3 0 4
    7 0 4 5
    8 3 0 6
    

    【讨论】:

      【解决方案2】:

      对于基本 R 选项,您可以使用 colSums:

      df[, colSums(df) != 0]
      
        a b d
      1 0 2 2
      2 2 3 5
      3 5 0 1
      4 7 0 2
      5 2 1 3
      6 3 0 4
      7 0 4 5
      8 3 0 6
      

      表达式colSums(df) != 0boolean,并且只对那些全为零的列才为真。请注意,此答案假定您只希望列中有正值。

      一种严格查找不全为零的列的答案的表达方式是断言该列的最小值或最大值为零:

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

      【讨论】:

        【解决方案3】:

        仅使用 base-r,您可以使用 apply(df, 2, function(x) all(x == 0)) 仅获取只有零值的列。将NULL 分配给这些列会删除这些值。

        a <- c(0,2,5,7,2,3,0,3)
        b <- c(2,3,0,0,1,0,4,0)
        c <- c(0,0,0,0,0,0,0,0)
        d <- c(2,5,1,2,3,4,5,6)
        
        df <- data.frame(a,b,c,d)
        
        df[apply(df, 2, function(x) all(x == 0))] <- NULL
        df
        #>   a b d
        #> 1 0 2 2
        #> 2 2 3 5
        #> 3 5 0 1
        #> 4 7 0 2
        #> 5 2 1 3
        #> 6 3 0 4
        #> 7 0 4 5
        #> 8 3 0 6
        

        快速基准测试

        如果您对速度感兴趣(不一定是代码可读性(可以讨论...)):

        library(dplyr)
        dplyr_version <- function(d) {
          d %>%
            select(where(~ any(. != 0)))
        }
        base_version <- function(d) {
          d[apply(df, 2, function(x) all(x == 0))] <- NULL
          d
        }
        colsum_version <- function(d) {
          d[, colSums(d) != 0]
        }
        
        
        bench::mark(
          dplyr_version(df),
          base_version(df),
          colsum_version(df)
        )
        #> # A tibble: 3 x 13
        #>   expression          min  median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result
        #>   <bch:expr>        <bch> <bch:t>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm> <list>
        #> 1 dplyr_version(df) 883µs 928.5µs     1057.    1.07MB     24.3   478    11      452ms <df[,…
        #> 2 base_version(df)   70µs  77.6µs    11860.      480B     26.6  5344    12      451ms <df[,…
        #> 3 colsum_version(df)  41.2µs  45.1µs    21580.      240B     15.1  9993     #> 7      463ms
        #> # … with 3 more variables: memory <list>, time <list>, gc <list>
        

        并测试更大的数据集:

        # Testing for a larger file
        set.seed(251)
        large_df <- df %>% sample_n(1e7, replace = TRUE)
        bench::mark(
          dplyr_version(large_df),
          base_version(
          colsum_version(large_df)
        )
        
        #> # A tibble: 3 x 13
        #>   expression                 min median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time
        #>   <bch:expr>              <bch:> <bch:>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm>
        #> 1 dplyr_version(large_df) 77.5ms 85.6ms      12.0     114MB     12.0     3     3      250ms
        #> 2 base_version(large_df)  65.8µs 69.5µs   14067.       480B     12.6  6720     6      478ms
        #> 3 colsum_version(large_df) 121.6ms 122.1ms      8.19     229MB     8.19     2     2
        #> # … with 4 more variables: result <list>, memory <list>, time <list>, gc <list>
        

        我们看到,在这种情况下,基础版本在更大的数据集上速度更快。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-12-01
          • 1970-01-01
          • 2017-12-14
          • 2016-07-09
          • 2020-07-07
          • 1970-01-01
          • 2018-10-23
          相关资源
          最近更新 更多