#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 = " "))