大家好,又见面了,我是你们的朋友全栈君。
近期写R代码,经常用dplyr::case_when结合stringr::str_detect进行条件判断。
痛点:判断条件可能会改或增删,全写在case_when里,代码冗余且不利于复制和维护,stackoverflow找了一圈,没发现好的解决方案,干脆自己写了一个通用代码以自动生成批量case_when判断。
先上代码:
代码语言:javascript复制allCaseWhen <<- function(x,pattern,result){
x1 <- str_flatten(map2_chr(result,pattern,~str_glue("str_detect(x,'{.y}')~'{.x}',")))
x2 <- str_glue("function(x) case_when({x1})")
fx <- eval(parse(text=x2))
fx({
{
x}})}
需要用到的包:
代码语言:javascript复制 library(purrr)
library(stringr)
使用示例:
初始表tibble(fruit=stringr::fruit)
想实现字母a开头为’starts with a’,字母e结尾为’ends with e’ 等若干条件。结果如下图:
单纯用case_when,需要写成
代码语言:javascript复制tibble(fruit=stringr::fruit) %>%
mutate(
category=case_when(
str_detect(fruit,'^a')~'starts with a',
str_detect(fruit,'e$')~'ends with e',
str_detect(fruit,'o')~'contains o',
str_detect(fruit,'(an)|(ch)')~'contains an or ch'
)
)
如果有其他表有类似的应用,你得把条件抄一遍,实在繁琐。
用改良后的allCaseWhen会简单很多,两步解决:
1. 表格形式列出条件
代码语言:javascript复制conditions <-
tribble(
~pattern,~result,
'^a','starts with a',
'e$','ends with e',
'o','contains o',
'(an)|(ch)','contains an or ch'
)
或者写在Excel里,
然后复制单元格,用conditions <- clipr::read_clip_tbl()
读进R
2. allCaseWhen走起
代码语言:javascript复制tibble(fruit=stringr::fruit) %>%
mutate(
category=
allCaseWhen(fruit,
conditions$pattern, #读取条件
conditions$result #返回结果
)
)
搞定。
函数的核心依然是case_when,条件为真即停止,所以效率上没有损失。
如果想改条件,在conditions里放肆增删改,改完再跑一遍allCaseWhen即可。
没有写默认条件,因为没必要,可以用coalesce()
处理。
以上。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。