【问题标题】:how to use case_when and grep together to define a new varaible如何使用 case_when 和 grep 一起定义一个新变量
【发布时间】:2020-12-22 01:00:29
【问题描述】:

我有一个看起来像这样的数据,

可以使用代码构建:

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" 并且我们在 Location 中找到“OH”,则注释 ="Female in OH" 如果 Gender=="F" 并且我们在 Location 中找不到“OH”,则评论 ="Female in Other" 如果 Gender=="M" 并且我们在 Location 中找到“OH”,则评论 ="Male in OH" 如果 Gender=="M" 并且我们在 Location 中找不到“OH”,则评论 ="Male in Other"

所以我的代码是

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

这行不通。谁能给我一些指导?

【问题讨论】:

  • 使用grepl 而不是grep。前者将根据需要返回一个布尔值,后者返回匹配项的索引,这不是您所期望的。
  • 我试过grepl 仍然得到错误代码Error: must be a character vector, not a logical vector
  • 另外三件事:(1)不要在mutate中使用df$,这几乎肯定是错误的; (2) 将你上次的NA 改为NA_character_; (3) 将您的错字Location2 更改为Location。通过这三个更改,它对我有用。 (顺便说一句:“它不起作用” 根本没有帮助。如果您在问题中包含文字错误文本,它通常会帮助更多。)
  • 您的最后一个TRUE~... 不是必需的,因为如果没有匹配项,case_when 的默认操作是分配NA 的特定于类的版本。 (你知道NA至少有七种类型吗?)
  • 谢谢。我输入TRUE~ 以防万一我错过了其他任何内容。

标签: r case-when


【解决方案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" & grepl("OH", Location)~"Female in OH",
                                Gender=="F" & !grepl("OH", Location)~ "Female in Other",                        
                                Gender=="M" & grepl("OH", Location)~ "Male in OH",
                                Gender=="M" & !grepl("OH", Location)~ "Male in other"))
    

    我删除了 NA 部分,因为您涵盖了所有情况,并且 NA 是没有其他匹配项时的默认值。但是,如果您明确需要它,那么您应该使用 NA 的类型化版本作为字符。

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

    【讨论】:

    • 没有匹配项的默认操作是分配一个NA,因此添加主要是声明性的和“完整的”,它产生的结果与没有它的结果相同。
    • @r2evans 很高兴知道。我应该测试一下。
    • 在我测试之前我也不确定:-)
    【解决方案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 = " "))
    
     
    

    【讨论】:

      猜你喜欢
      • 2021-11-09
      • 1970-01-01
      • 2023-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多