Упростить выбор похожих именованных столбцов по условию - PullRequest
0 голосов
/ 03 сентября 2018

Пример кода ниже работает, но у меня вопрос, как я могу написать это с меньшим количеством кода и более элегантно?

Дело в том, что у меня есть столбцы с похожими именами. В этом примере я хочу выбрать все столбцы, начинающиеся с B и где все находятся со значением FALSE.

set.seed(0)

df <- data.frame(A = sample(c(T, F), 100, replace=T),
                 B1 = sample(c(T, F), 100, replace=T),
                 B2 = sample(c(T, F), 100, replace=T),
                 B3 = sample(c(T, F), 100, replace=T))

n <- names(df)[startsWith(names(df), 'B')]

result <- df[df$B1 == FALSE & df$B2 == FALSE & df$B3 == FALSE, n]

print(result)

Результат

      B1    B2    B3
1  FALSE FALSE FALSE
26 FALSE FALSE FALSE
31 FALSE FALSE FALSE
35 FALSE FALSE FALSE
51 FALSE FALSE FALSE
66 FALSE FALSE FALSE
70 FALSE FALSE FALSE
84 FALSE FALSE FALSE

Что я пробовал это с неожиданными результатами

df[df[,n] == FALSE, n]

Ответы [ 5 ]

0 голосов
/ 03 сентября 2018

В base R мы можем сделать

df[!Reduce(`|`, df[grep("^B", names(df))]),]
#       A    B1    B2    B3
#1  FALSE FALSE FALSE FALSE
#26  TRUE FALSE FALSE FALSE
#31  TRUE FALSE FALSE FALSE
#35  TRUE FALSE FALSE FALSE
#51 FALSE FALSE FALSE FALSE
#66 FALSE FALSE FALSE FALSE
#70  TRUE FALSE FALSE FALSE
#84  TRUE FALSE FALSE FALSE
0 голосов
/ 03 сентября 2018

Я бы сделал это так:

ваши данные:

df <- data.frame(A = sample(c(T, F), 100, replace=T),
                 B1 = sample(c(T, F), 100, replace=T),
                 B2 = sample(c(T, F), 100, replace=T),
                 B3 = sample(c(T, F), 100, replace=T))

Код:

df<- as.data.frame(!df[,grepl("^B",names(df))])

!df[apply(df,1,all),]

результат:

#      B1    B2    B3
#1  FALSE FALSE FALSE
#26 FALSE FALSE FALSE
#31 FALSE FALSE FALSE
#35 FALSE FALSE FALSE
#51 FALSE FALSE FALSE
#66 FALSE FALSE FALSE
#70 FALSE FALSE FALSE
#84 FALSE FALSE FALSE
0 голосов
/ 03 сентября 2018

с тидиверсом:

df %>% select(matches("^B")) %>% filter_all(all_vars(.==FALSE))

или, если вы хотите проверить номера строк:

df %>% mutate(id=row_number()) %>%                  # copy row number to new variable 
  select(id,matches("^B")) %>%                      # keeps id and variables beginning with B
  filter_at(vars(matches("^B")),                    # for variables beginning with B
            all_vars(.==FALSE))                     # keep rows where all are FALSE
#  id    B1    B2    B3
#1  1 FALSE FALSE FALSE
#2 26 FALSE FALSE FALSE
#3 31 FALSE FALSE FALSE
#4 35 FALSE FALSE FALSE
#5 51 FALSE FALSE FALSE
#6 66 FALSE FALSE FALSE
#7 70 FALSE FALSE FALSE
#8 84 FALSE FALSE FALSE
0 голосов
/ 03 сентября 2018

Быстрая альтернатива base-R:

df[!do.call(pmax, df[n]), n]

       B1    B2    B3
1  FALSE FALSE FALSE
26 FALSE FALSE FALSE
31 FALSE FALSE FALSE
35 FALSE FALSE FALSE
51 FALSE FALSE FALSE
66 FALSE FALSE FALSE
70 FALSE FALSE FALSE
84 FALSE FALSE FALSE

EDIT

Оставаясь ближе к исходной попытке, которую вы могли бы сделать:

df[apply(df[n] == FALSE, 1, all), n] 
# or
df[apply(!df[n], 1, all), n]
0 голосов
/ 03 сентября 2018

В базе R мы можем выбрать столбцы, которые начинаются с «B», а затем выбрать строки, сумма которых равна 0, используя rowSums.

inds <- grepl("^B", names(df))
df[rowSums(df[inds]) == 0, inds]

#      B1    B2    B3
#1  FALSE FALSE FALSE
#26 FALSE FALSE FALSE
#31 FALSE FALSE FALSE
#35 FALSE FALSE FALSE
#51 FALSE FALSE FALSE
#66 FALSE FALSE FALSE
#70 FALSE FALSE FALSE
#84 FALSE FALSE FALSE

Или, как упоминает @snoram, чтобы сделать его более кратким, мы можем сделать

df[!rowSums(df[inds]), inds]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...