R: получить столбцы, которые имеют значение только 0 - PullRequest
3 голосов
/ 29 марта 2020

пример кода:

df:

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

Существует только 1 строка и 3000+ столбцов.

Мне было интересно, как я могу выбрать только столбцы с 0 (из которых, как я уже подтвердил, просматривая данные.)

Ожидается что-то вроде этого:

res:

#   d                        e                      f
# 1 0                        0                      0

Ответы [ 4 ]

2 голосов
/ 29 марта 2020

Опция с Filter из base R

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

Или с 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))
2 голосов
/ 29 марта 2020

Если есть только одна строка, вы можете отменить столбцы (как 0 == FALSE):

res <- df[, !df]

Или проверить, где colSums 0:

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

Вывод:

  d e f
1 0 0 0

Данные:

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))

Тест показывает, что @ akrun's Filter является самым быстрым на данный момент (не включая dplyr вариант, поскольку он самый медленный):

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

Код для теста:

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

)
2 голосов
/ 29 марта 2020

Возможно, самое простое решение - это (используя данные @ arg0naut91):

df[, df==0]
  d e f
1 0 0 0
1 голос
/ 29 марта 2020
df[,which(df[1,]==0)] 

должен сделать работу.

...