【问题标题】:use case_when in R looking at the number at the end of a column name is greater than the number at the end of another column name用 case_when 在 R 中查看列名末尾的数字大于另一个列名末尾的数字
【发布时间】:2019-10-29 09:19:49
【问题描述】:

我想在 dplyr 中使用 case_when() 来创建一个新的分类列,说明一个人在培训中的当前状态。

我有一个看起来像这样的小标题:

library(dplyr)
problem <- tibble(name = c("Angela", "Claire", "Justin"),
                  status_1 = c("Registered", "No Action", "Completed"),
                  status_2 = c("Withdrawn", "No Action", "Registered"),
                  status_3 = c("No Action", "Registered", "Withdrawn"))

如果此人曾经完成过课程,则他们的状态应该是完成(即使他们在以后不小心再次注册了该课程,作为本例中 Justin 的证据)。如果他们尚未完成课程,则应注册他们的状态并且以后的状态不会撤消该课程,例如“不采取行动”或“撤回”。如果他们已经完成,他们应该是状态“未采取”什么都没有,或者在他们注册之后撤回。

在本例中,最终数据集应如下所示:

library(dplyr)
solution <- tibble(name = c("Angela", "Claire", "Justin"),
                   status_1 = c("Registered", "No Action", "Completed"),
                   status_2 = c("Withdrawn", "No Action", "Registered"),
                   status_3 = c("No Action", "Registered", "Withdrawn"),
                   current = c("Not Taken", "Registered", "Completed"))

贾斯汀完成了,因为他在任何时候完成了课程。安吉拉没有被带走,因为她取消了注册。 Claire 已注册,因为她的最远身份已注册。

这是我目前所拥有的。它正确地分类了贾斯汀和克莱尔,但错误地分类了安吉拉。我理解为什么它确实对她进行了错误分类,但我不知道如何进行注册,因为它涉及查看后面的数字,并且 R 正确地将变量名称视为一个字符。

library(dplyr)
library(purrr)
solution <- problem %>%
  mutate(current_status = pmap_chr(select(., contains("status")), ~
                                     case_when(any(str_detect(c(...), "(?i)Completed")) ~ "Completed",
                                               any(str_detect(c(...), "(?i)Registered")) ~ "Registered", 
                                               any(str_detect(c(...), "(?i)No Action")) | any(str_detect(c(...), "(?i)Withdrawn")) ~ "Not Taken",
                                               TRUE ~ "NA"))) 

谢谢!

【问题讨论】:

    标签: r dplyr conditional-statements purrr


    【解决方案1】:

    这是使用applycase_when 的一种方法。 apply 一次遍历 problem 的所有行,并根据 case_when 条件计算结果。

    problem %>% 
     mutate(
       current = 
         apply(select(., starts_with("status")), 1, function(x) {
           case_when(
             "Completed" %in% x ~ "Completed",
             which.max(x=="Registered") > which.max(x %in% c("No Action","Withdrawn")) ~ "Registered",
             TRUE ~ "Not Taken"
           )
         })
      )
    
    # A tibble: 3 x 5
      name   status_1   status_2   status_3   current   
      <chr>  <chr>      <chr>      <chr>      <chr>     
    1 Angela Registered Withdrawn  No Action  Not Taken 
    2 Claire No Action  No Action  Registered Registered
    3 Justin Completed  Registered Withdrawn  Completed 
    

    在管道之外,你可以简单地做 -

    problem$current <- select(problem, starts_with("status")) %>% 
      apply(., 1, function(x) {
        case_when(
          "Completed" %in% x ~ "Completed",
          which.max(x == "Registered") > which.max(x %in% c("No Action", "Withdrawn")) ~ "Registered",
          TRUE ~ "Not Taken"
        )
      })
    

    【讨论】:

    • 谢谢!两个问题,首先,如果我希望它跨状态列运行,我将如何修改它?在我的实际数据集中,我有很多列,其中一些有状态,一些没有。其次,出于好奇,“x”在这种情况下是什么意思,比如“Completed”%in% x?
    • @J.Sabree 我已将代码更新为仅查看以status 开头的列。 apply(df, 1, FUN) 一次遍历数据帧 1 的所有行。所以x 这边是df 的一排。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 2016-06-19
    • 1970-01-01
    • 2015-07-25
    • 2022-11-15
    • 1970-01-01
    相关资源
    最近更新 更多