как использовать case_when и grep вместе, чтобы определить новую переменную

#r #case-when

#r #случай, когда

Вопрос:

У меня есть данные, которые выглядят следующим образом,

введите описание изображения здесь

Это может быть построено с использованием кодов:

 df<-structure(list(Gender = c("M", "F", "M", "F", "F"), Location = c("Cleveland, OH", 
"New Olreans, LA", "Chicago, IL", "Strongsville, OH", "Boston, MA"
)), row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"
))
 

Я хочу создать переменную «комментарий» следующим образом:
введите описание изображения здесь

Правило таково: если Gender==»F» и мы находим «OH» в местоположении, то comment =»Женщина в OH», если Gender ==»F» и мы не можем найти «OH» в местоположении, тогда comment =»Женщина в другом», если Gender ==»M» и мы находим «OH» в Location, затем comment =»Мужчина в OH», если Gender ==»M» и мы не можем найти «OH» в Location, тогда comment =»Мужчина в Other»

Итак, мои коды

  df<-df %>% 
     mutate(Comment = case_when(Gender=="F" amp; grep("OH", df$Location)~"Female in OH",
                            Gender=="F" amp; !grep("OH", df$Location)~ "Female in Other",                        
                            Gender=="M" amp; grep("OH", df$Location2)~ "Male in OH",
                            Gender=="M" amp; !grep("OH", df$Location)~ "Male in other)",
                            TRUE~NA))
 

Это не сработает. Кто-нибудь может дать мне некоторые рекомендации по этому поводу?

Комментарии:

1. Используйте grepl вместо grep . Первый вернет логическое значение по желанию, последний возвращает индексы совпадений, что, похоже, не то, что вы ожидаете.

2. Я пытался grepl и все равно получаю код ошибки Error: must be a character vector, not a logical vector

3. Три другие вещи: (1) не используйте df$ внутри mutate , это почти наверняка неправильно; (2) измените свой последний NA на NA_character_ ; (3) Измените свою опечатку Location2 на Location . С этими тремя изменениями это работает для меня. (Кстати: «это не сработает» совсем не полезно. Если вы включаете буквальный текст ошибки в свой вопрос, это часто помогает намного больше.)

4. Однако в последнем TRUE~... нет необходимости, поскольку действие по умолчанию case_when , если совпадений нет, заключается в назначении версии, зависящей от класса NA . (Знаете ли вы, что существует как минимум семь типов NA ?)

5. Спасибо. Я вставил TRUE~ на всякий случай, если я что-то еще пропустил.

Ответ №1:

Я думаю, что это можно немного упростить вместо проверки всех возможных условий.

 vec <- c('M' = 'Male', 'F' = 'Female')

transform(df, Comment = paste(vec[Gender], 
                       ifelse(grepl('OH', Location), 'in OH', 'in Other')))

#  Gender Location         Comment        
#  <chr>  <chr>            <chr>          
#1 M      Cleveland, OH    Male in OH     
#2 F      New Olreans, LA  Female in Other
#3 M      Chicago, IL      Male in other  
#4 F      Strongsville, OH Female in OH   
#5 F      Boston, MA       Female in Other
 

Ответ №2:

Используйте grepl вместо grep , чтобы получать логические значения TRUE / FALSE, а не индексы. Например (а также исправление других опечаток)

 df %>% 
     mutate(Comment = case_when(Gender=="F" amp; grepl("OH", Location)~"Female in OH",
                            Gender=="F" amp; !grepl("OH", Location)~ "Female in Other",                        
                            Gender=="M" amp; grepl("OH", Location)~ "Male in OH",
                            Gender=="M" amp; !grepl("OH", Location)~ "Male in other"))
 

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

 df %>% 
  mutate(Comment = case_when(Gender=="F" amp; grepl("OH", Location)~"Female in OH",
                             Gender=="F" amp; !grepl("OH", Location)~ "Female in Other",                        
                             Gender=="M" amp; grepl("OH", Location)~ "Male in OH",
                             Gender=="M" amp; !grepl("OH", Location)~ "Male in other",
                             TRUE~NA_character_))
 

Комментарии:

1. Действие по умолчанию, не имеющее совпадений, заключается в назначении NA , так что добавление в основном декларативное и «полное», оно дает те же результаты, что и без него.

2. @r2evans Полезно знать. Я должен был это протестировать.

3. Я не был уверен в этом, пока не протестировал его тоже 🙂

Ответ №3:

На самом деле это всего лишь вариант ответа @Ronak Shah.
Аббревиатура состояния обнаруживается с str_extract помощью и "OH" по мере параметризации основного состояния.

 gender_vec <- c('M' = 'Male', 'F' = 'Female')
state_map <- function(s, target = "OH") if_else(s == target, s, "Other")

df %>%
  mutate(Comment = str_c(recode(Gender, !!!gender_vec), "in", 
                         state_map(str_extract(Location, "(\w{2})$")), 
                         sep = " "))