R: get columns that only have value 0

Viewed 66

sample code:

df:

#                        a                       b                       c
# 1 -0.0010616345688829504  -4.1135727372109387e-05 -0.0001814242939304348

There is only 1 row and 3000+ columns.

I was wondering how I can select only the columns with 0 (of which there is as I have confirmed looking at the data.)

Expecting something like this:

res:

#   d                        e                      f
# 1 0                        0                      0
4 Answers

If there is only one row, you could negate the columns (as 0 == FALSE):

res <- df[, !df]

Or check for where colSums are 0:

res <- df[, colSums(df) == 0]

Output:

  d e f
1 0 0 0

Data:

df <- structure(list(a = -0.00106163456888295, b = -4.11357273721094e-05, 
    c = -0.000181424293930435, d = 0, e = 0, f = 0), class = "data.frame", row.names = c(NA, 
-1L))

A benchmark shows @akrun's Filter to be the fastest by far (haven't included the dplyr variant since it's by far the slowest):

Unit: milliseconds
    expr     min       lq     mean   median       uq      max neval
   which 25.1935 26.95415 29.42942 28.00300 31.34740 181.5487  1000
      == 14.2807 15.25200 16.84471 15.73310 16.92505 182.6126  1000
  Filter  1.6767  1.80705  2.02523  1.90270  1.99135   7.5026  1000
 colSums 11.0489 11.85425 12.83663 12.26115 13.04670  23.9469  1000
       ! 14.2278 15.07710 16.55270 15.55400 16.76835 187.0145  1000

enter image description here

Code for benchmark:

set.seed(3234)

ncols <- 3000
df <- as.data.frame(matrix(rpois(ncols, 0.5), ncol = ncols))

bench <- microbenchmark::microbenchmark(

  which = df[, which(df[1, ] == 0)],
  `==` = df[, df == 0],
  Filter = Filter(function(x) all(x == 0), df),
  colSums = df[, colSums(df) == 0],
  `!` = df[, !df],
  times = 1000

)

Arguably the simplest solution is this (using @arg0naut91's data):

df[, df==0]
  d e f
1 0 0 0

An option with Filter from base R

Filter(function(x) all(x == 0), df)
#   d e f
#1 0 0 0

Or with dplyr

library(dplyr)
df %>%
   select_if(~ all(. == 0))
#  d e f
#1 0 0 0

data

df <- structure(list(a = -0.00106163456888295, b = -4.11357273721094e-05, 
    c = -0.000181424293930435, d = 0, e = 0, f = 0), class = "data.frame", row.names = c(NA, 
-1L))
df[,which(df[1,]==0)] 

should do the job.

Related