Как изменить новый столбец со значением yes или no, если хотя бы один столбец от col7 до col10 равен 4 в r с помощью dplyr?

У меня есть следующие данные:

 col1 <- c(0.1,0.2,0.0,0.5,0.6)
 col2 <- c(2,2,4,5,6)
 col3 <- c(1,4,3,4,5) 
 col4 <- c(2,3,4,4,6)
 col5 <- c(5,3,3,2,1)
 data.frame(col1,col2,col3,col4,col5)

   col1 col2 col3 col4 col5
 1  0.1    2    1    2    5
 2  0.2    2    4    3    3
 3  0.0    4    3    4    3
 4  0.5    5    4    4    2
 5  0.6    6    5    6    1

Я хотел бы добавить новый столбец со значением «да», где в каждой строке хотя бы один столбец от столбца 2 до столбца 5 равен 4 и «нет», если данные не соответствуют критериям.

Таким образом, результат будет выглядеть так:

   col1 col2 col3 col4 col5 col6
 1  0.1    2    1    2    5  no
 2  0.2    2    4    3    3  yes
 3  0.0    4    3    4    3  yes
 4  0.5    5    4    4    2  yes
 5  0.6    6    5    6    1  no

вот моя команда:

new.df <- df %>% mutate(df, col6 = funs(ifelse(abs(vars(c(2:5) == 4),"yes", "no")

Но я не могу получить требуемый результат. Вы знаете, как я могу использовать функции dplyr, mutate и if else для получения результата?


person say.ff    schedule 20.08.2018    source источник


Ответы (3)


Мы можем суммировать, когда ячейка == 4, используя rowSums

library(dplyr)
df %>% mutate(col6 = ifelse(rowSums(.[,c(2:5)]==4)>0, 'yes', 'no'))

col1 col2 col3 col4 col5 col6
1  0.1    2    1    2    5   no
2  0.2    2    4    3    3  yes
3  0.0    4    3    4    3  yes
4  0.5    5    4    4    2  yes
5  0.6    6    5    6    1   no

Используя предложение @thelatemail, мы можем переписать ifelse, как показано ниже:

df %>% mutate(col6 = ifelse(Reduce(`|`, lapply(.[,c(2:5)], `==`, 4)), 'yes', 'no'))
person A. Suliman    schedule 20.08.2018
comment
И функциональная альтернатива части rowSums будет Reduce(`|`, lapply(dat[-1], `==`, 4)), если кто-то склонен к этому. - person thelatemail; 20.08.2018
comment
@thelatemail хорошее использование == как функции, спасибо за трюк. - person A. Suliman; 20.08.2018

Вы можете попробовать с any

ifelse(apply(df[,-1]==4,1,any),'yes','no')
[1] "no"  "yes" "yes" "yes" "no" 
person BENY    schedule 20.08.2018

Вот несколько подходов:

1) rowSums Сравните все сравнения, кроме col1, с 4, просуммируйте сравнения и для каждого строго положительного результата выберите yes else no.

library(dplyr)

dd %>% 
  mutate(col6 = if_else(rowSums(select(., -col1) == 4) > 0, "yes", "no"))

giving:

  col1 col2 col3 col4 col5 col6
1  0.1    2    1    2    5   no
2  0.2    2    4    3    3  yes
3  0.0    4    3    4    3  yes
4  0.5    5    4    4    2  yes
5  0.6    6    5    6    1   no

1a) Уменьшить. Вариант этого с использованием Reduce:

dd %>% 
  mutate(col6 = 
    if_else(Reduce("|", (select(., -col1) == 4) %>% as.data.frame), "yes", "no"))

2) gathr Преобразуйте в развернутую форму, резюмируйте и снова присоедините к исходному фрейму данных.

library(dplyr)
library(tidyr)

dd %>%
  mutate(seq = 1:n()) %>%
  left_join(gather(., key, value, -seq, -col1) %>%
    group_by(seq) %>%
    summarize(col6 = if_else(any(value == 4), "yes", "no")) %>%
    ungroup) %>%
  select(-seq)

Если col1 имеет уникальные значения, как в образце данных, показанном в вопросе, то его можно использовать вместо seq сокращения кода до:

dd %>%
  left_join(gather(., key, value, -col1) %>%
    group_by(col1) %>%
    summarize(col6 = if_else(any(value == 4), "yes", "no")) %>%
    ungroup)
person G. Grothendieck    schedule 20.08.2018