Как вы оцениваете набор условий и создаете новый столбец на основе списка столбцов? - PullRequest
1 голос
/ 24 апреля 2020

Я хотел бы взять список (или отфильтровать) набор столбцов с одинаковыми именами в кадре данных, оценить значение этих столбцов для каждой строки, а затем создать новый столбец с результатом.

Сейчас я использую case_when, но я не знаю, как предоставить какой-либо подстановочный знак или список определенных столбцов.

Я хотел бы взять список или создать фильтр столбцов, потому что я хочу оценивать несколько столбцов в кадре данных, а не просто несколько. Наличие длинного списка столбцов в case_when кажется неэффективным, когда имена столбцов очень похожи друг на друга.

# Dummy data
ignore1 <- c(1, 0, 0)
ignore2 <- c(1, 0, 1)
col1 <- c(0, 1, 0)
col2 <- c(0, 1, 1)
col3 <- c(0, 1, 0)

df <- data.frame(ignore1, ignore2, col1, col2, col3)
df %>% 
  mutate(evaluation = case_when(
    col1 == 0| col1 == 0 | col1 == 0  ~ "Failed",
    TRUE ~ "Passed"
    )
  )

Это ожидаемый результат:

  ignore1 ignore2 col1 col2 col3 evaluation
1       1       1    0    0    0     Failed
2       0       0    1    1    1     Passed
3       0       1    0    1    0     Failed

, где проходит строка 2, потому что col1, col2, col3 all имеют значение 1.

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

Мы можем просто использовать rowSums, чтобы сделать этот эффективный

i1 <- startsWith(names(df), 'col')
c( "Failed",  "Passed")[(rowSums(df[i1] == 1) == 3) + 1]
#[1] "Failed" "Passed" "Failed"

или другой base R эффективный вариант Reduce

c("Failed", "Passed")[Reduce(`&`, df[i1]) +1]
#[1] "Failed" "Passed" "Failed"

ПРИМЕЧАНИЕ. Оба решения base R компактны и очень эффективны


Или с &

library(dplyr)
df %>% 
     mutate(evaluation =  c('Failed', 'Passed')[1 + (col1 & col2 & col3)])
#  ignore1 ignore2 col1 col2 col3 evaluation
#1       1       1    0    0    0     Failed
#2       0       0    1    1    1     Passed
#3       0       1    0    1    0     Failed

Или мы можем иметь rowSums в пределах dplyr

df %>%
   mutate(evaluation = c("Failed", "Passed")[(rowSums(.[i1] == 1) == 3) + 1])

ПРИМЕЧАНИЕ : Оба решения очень эффективны и не используют пакеты, которые на самом деле не нужны

Или, если нам нужны какие-то пакеты, используйте magrittr с purrr

library(magrittr)
library(purrr)
df %>% 
   mutate(evaluation = select(., starts_with('col')) %>% 
                          reduce(`&`) %>%
                          add(1) %>%
                          c("Failed", "Passed")[.])
#  ignore1 ignore2 col1 col2 col3 evaluation
#1       1       1    0    0    0     Failed
#2       0       0    1    1    1     Passed
#3       0       1    0    1    0     Failed

ПРИМЕЧАНИЕ. Здесь также мы не перебираем строки, поэтому оно должно быть эффективным

0 голосов
/ 24 апреля 2020

Поскольку вы хотите выполнить построчную операцию, мы можем использовать pmap варианты

library(dplyr)
library(purrr)

df %>% mutate(result =c("Passed","Failed")[pmap_lgl(select(., starts_with('col')),
                       ~any(c(...) == 0)) + 1])

#  ignore1 ignore2 col1 col2 col3 result
#1       1       1    0    0    0 Failed
#2       0       0    1    1    1 Passed
#3       0       1    0    1    0 Failed

В базе R мы можем использовать apply построчно:

cols <- startsWith(names(df), 'col')
df$Result <- c("Passed", "Failed")[apply(df[cols] == 0, 1, any) + 1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...