Как применить несколько условий при использовании %in%?

У меня есть пример, в котором я хочу создать столбец m, где если x1, x2 или x3 = «A» или «B», то m = 1, иначе m = 0.

df <- data.frame(x1 = LETTERS[1:10], x2 = LETTERS[2:11], x3 = LETTERS[3:12])


df <-  df%>% 
   mutate(m = ifelse(df[,paste0("x",1:3)] %in% c("A","B") ,1,0))

при использовании этого кода он не работает, и я не знаю, где ошибка и как ее исправить. Спасибо.

%in% в данном случае не будет работать, если вы не примените функцию к каждому столбцу: sapply(df, \(x) +x %in% c("A","B"))
Maël 17.05.2024 11:52

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

An116 17.05.2024 11:55

Я бы предложил использовать функцию case_when вместо ifelse. Затем вы можете указать оператор x %in% c('A', 'B') ~ 1 для всех переменных от x1 до x3, а затем использовать .default = 0, чтобы установить значение в ноль, в противном случае

A. Bohyn 17.05.2024 11:56

Спасибо. не могли бы вы написать код с помощью case_when, поскольку я никогда раньше не использовал эту функцию

An116 17.05.2024 11:59

я пробовал использовать case_when, но у меня та же проблема при использовании %in%. Это не работает

An116 17.05.2024 12:12
df %>% rowwise() %>% mutate(m = case_when(any(c(x1,x2,x3) %in% c("A","B"))~1, .default=0))
Marco Sandri 17.05.2024 12:14

Теперь у меня другая проблема: у меня так много столбцов, а вместо x1,x2,x3 я хочу использовать Paste0, но с этим кодом он не работает. как справиться с этим с помощью Paste0?

An116 17.05.2024 12:30
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
7
81
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Вы можете использовать rowSums. Лучше используйте grep вместо paste подхода.

> df |> 
+   transform(m=+(rowSums(sapply(df[grep('^x\\d$', names(df))], `%in%`, c('A', 'B'))) > 0))
   x1 x2 x3 m
1   A  B  C 1
2   B  C  D 1
3   C  D  E 0
4   D  E  F 0
5   E  F  G 0
6   F  G  H 0
7   G  H  I 0
8   H  I  J 0
9   I  J  K 0
10  J  K  L 0

dplyr::mutate тоже должно работать, не устанавливал. По возможности избегайте ifelse и тому подобного, это просто медленно.

Иногда вы можете воспользоваться особой структурой ваших данных. Если вы ищете A и B только среди заглавных букв A-Z, вы можете сделать:

cols <- c("x1", "x2", "x3")

df$m <- as.integer(do.call(pmin, df[cols]) < "C")

   x1 x2 x3 m
1   A  B  C 1
2   B  C  D 1
3   C  D  E 0
4   D  E  F 0
5   E  F  G 0
6   F  G  H 0
7   G  H  I 0
8   H  I  J 0
9   I  J  K 0
10  J  K  L 0

Не нужно проверять по строкам, вы можете попробовать

df$m <- +(rowMeans(`dim<-`(as.matrix(df) %in% c("A", "B"), dim(df))) > 0)

или

df$m <- +(rowMeans(`dim<-`(unlist(df, FALSE, FALSE) %in% c("A", "B"), dim(df))) > 0)

и вы получите

> df
   x1 x2 x3 m
1   A  B  C 1
2   B  C  D 1
3   C  D  E 0
4   D  E  F 0
5   E  F  G 0
6   F  G  H 0
7   G  H  I 0
8   H  I  J 0
9   I  J  K 0
10  J  K  L 0

Разве unlist() не будет намного быстрее, чем as.matrix()?

s_baldur 17.05.2024 13:24

да, это быстрее @s_baldur

ThomasIsCoding 17.05.2024 13:25

Для тех из нас, кто забыл :-), стоит отметить, что +(stuff) преобразует логические значения в числовые.

Carl Witthoft 17.05.2024 16:05

Вот вариант purrr::map (три варианта) с помощниками выбора, чтобы вы могли иметь больше столбцов со сложными именами:

library(tidyverse)

# Toy data
df <- data.frame(x1 = LETTERS[1:10], x2 = LETTERS[2:11], x3 = LETTERS[3:12])

# Just helpers
aux <- c("A", "B")
fn  <- \(x, y) any(x %in% y)

# Option 1 A `pmap`
df$m <- pmap_int(
  select(df, starts_with("x")), 
  \(...) some(list(...), \(x) fn(aux, x)))

# Option 2 `mutate` and `pmap`
df <- df %>% 
  mutate(n = pmap_int(
    select(., starts_with("x")), 
    \(...) some(list(...), \(x) fn(aux, x))))

# Option 3: rowwise, `mutate` and `map`
df <- df %>% 
  rowwise() %>% 
  mutate(o = map_int(
    list(c_across(starts_with("x"))),
    \(x) fn(aux, x))) %>% 
  ungroup() # Always ungroup it after a `rowwise` operation 

Выход:

> df
# A tibble: 10 × 6
   x1    x2    x3        m     n     o
   <chr> <chr> <chr> <int> <int> <int>
 1 A     B     C         1     1     1
 2 B     C     D         1     1     1
 3 C     D     E         0     0     0
 4 D     E     F         0     0     0
 5 E     F     G         0     0     0
 6 F     G     H         0     0     0
 7 G     H     I         0     0     0
 8 H     I     J         0     0     0
 9 I     J     K         0     0     0
10 J     K     L         0     0     0

Created on 2024-05-17 with reprex v2.1.0

Другие вопросы по теме