ifelse / case_when在字符向量中包含看似棘手的字符串时

时间:2020-06-15 17:57:39

标签: r dplyr data.table

我有一个死亡率数据帧,其中的字符向量(rac)每行包含不同的字符串。这些字符串标记了导致死亡的原因。有时,这些字符串之间有一个多余的空格(请参见id = 4, 5, 8)。有时它们恰好具有3个字符,而在另一些时候则具有4个字符。我要做的是逐行扫描并创建一个新列,以标记是否在rac中看到了特定的死亡原因。这是数据。

tdf <- structure(list(id = 1:10, rac = c("I250", "K922 R628", 
"C259 T149 X599", "K729 C80  J80  N288", "X72  S019", "C189", 
"C259 A419 K746 N390", "C349 C787 C793 C795 F179 I10  J449", 
"C349 J449 R628", "F03  N189 R628")), row.names = c(NA, -10L), 
class = "data.frame")

id = 8为例,在这里我可以轻松地创建一个名为cause_c的标志,该标志会在看到类似以下代码段的内容时记录C793C795的情况。

causex <- c("\\bC793|\\bC795")
tdf %>%
  mutate(
    cause_C = case_when(
      str_detect(rac, causex) ~ 1,
      TRUE ~ 0)
  ) -> tdf

这似乎可行,但是我希望能够在矢量仅显示3位数字的情况下进行扫描,例如C79,而在发生这种情况时,cause_C应该= 1。这也是创建标记的一种更有效的方法,因为这样我就不必拼出所有可能的代码版本(C793,C794,C79等),并且因为我有多种原因可以遍历和标记大约16种可能的死亡原因。但是,如果我尝试以下id = 8,则最终将全为0。

tdf %>%
  mutate(
    cause_C = case_when(
      str_sub(rac, 1, 3) == "C79" ~ 1,
      TRUE ~ 0)
  ) -> tdf

ifelse()\ case_when()解决方案缺少我一些东西,如果有人发现我的错误和解决方法,我将非常感激!哦,base-R,data.table(),dplyr(),所有解决方案都是受欢迎的,因为鉴于数据帧消耗的数据超过1.5 gig,我也很高兴看到速度比较。

谢谢!

阿尼

1 个答案:

答案 0 :(得分:1)

如果要使用data.table,是否考虑按诊断代码拆分行,然后使用grepl匹配所需诊断的向量?

library(data.table)

causex <- c("C793", "C795")

search_causex <- paste(causex, collapse = "|")

setDT(tdf, key = "rac")
tdf[, list(rac = unlist(strsplit(rac, " "))), by = id][
  , result := grepl(search_causex, rac)][
    result == TRUE]

如果要按较少的字符进行搜索,可以将其用于搜索模式:

search_causex <- "C79(.+)"

一种tidyverse类似的方法可能是:

library(tidyverse)

tdf %>%
  separate_rows(rac, sep = " ") %>%
  filter(grepl(search_causex, rac) == TRUE)