【问题标题】:Creating Dummy Variables from Multiple Character (string) Variables (r)从多个字符(字符串)变量创建虚拟变量 (r)
【发布时间】:2017-06-14 16:57:57
【问题描述】:

我需要从字符(字符串)变量创建一个虚拟变量(二进制) 我的数据如下所示:

dat <- tribble(
    ~pat_id, ~icd9_1, ~icd9_2,
    1, "414.01", "414.01",
    2, "411.89", NA,
    3, NA, "410.71",
    4, NA, NA,
    5, NA, "410.51",
    6, NA, "272.0, 410.71"
)
dat



# A tibble: 6 x 3
#         pat_id icd9_1        icd9_2
#          <dbl>  <chr>         <chr>
#              1 414.01        414.01
#              2 411.89          <NA>
#              3   <NA>        410.71
#              4   <NA>          <NA>
#              5   <NA>        410.51
#              6   <NA> 272.0, 410.71

我要新建三个二进制变量:

icd9_bin_1 == icd9_1 的二进制 (0/1)
icd9_bin_2 == icd9_2 的二进制 (0/1)
icd9_bin == icd9_1 的二进制或icd9_2

创建这些二进制变量的最快方法是什么?

我已经用0 替换了NAs,变成了一个因子然后重新编码,但是那 永远。

# get structure
dat$icd9_1 %>% str()
# get rid of NAs (replace with 0s)
dat$icd9_1[is.na(dat$icd9_1 )] <- 0
# turn into factor
dat$icd9_1 <- factor(dat$icd9_1)
# get levels 
dat$icd9_1 %>% levels()
# use fct_collapse
dat %>%
    mutate(icd9_bin_1 = fct_collapse(
        icd9_1,
        `icd9` = c("411.89","414.01"),
        `no icd9 dx` = c("0")))
# A tibble: 6 x 4
#   pat_id icd9_1        icd9_2 icd9_bin_1
#    <dbl> <fctr>         <chr>     <fctr>
#        1 414.01        414.01       icd9
#        2 411.89          <NA>       icd9
#        3      0        410.71 no icd9 dx
#        4      0          <NA> no icd9 dx
#        5      0        410.51 no icd9 dx
#        6      0 272.0, 410.71 no icd9 dx

我正在寻找更优雅的解决方案。想法?

【问题讨论】:

  • 第一行应该是二进制文件,因为它有两个非 na 列。您已将其标记为与仅指示列 9_1 的第二行相同。
  • 你只需要dat$icd9_bin_1 &lt;- if_else(is.na(dat$icd9_1), "no icd9 dx", "icd9")吗?我很累,所以我可能错过了什么......
  • @PierreLafortune 对此感到抱歉——我只是举例说明我是如何创建第一个二进制变量icd9_bin_1。创建这两个之后,我使用mutateif_elseicd9_1icd9_2 创建二进制文件
  • 试试dat[c('icd9_bin_1', 'icd9_bin_2')] &lt;- paste(c('yes', 'no')[is.na(dat[-1]) + 1L], rep(names(dat[-1]), each=nrow(dat)), sep='-')
  • @Phil,是的,它有效(并且代码行数更少)。我想我希望有一个dplyr 解决方案让我在一个管道中创建所有三个变量?实际数据在多个变量中具有多达 50 个不同的icd9 级别。

标签: r


【解决方案1】:

要手动创建二进制值,只需对每一列应用一个函数并获取列的or 来查找NA 都不是的行。

is_not_na <- function(...) Negate(is.na)(...)

dat %>%
  mutate(icd9_bin_1 = icd9_1 %>% is_not_na() %>% as.numeric(),
         icd9_bin_2 = icd9_2 %>% is_not_na() %>% as.numeric(),
         icd9_bin = as.numeric(icd9_bin_1 | icd9_bin_2))
#> # A tibble: 6 x 6
#>   pat_id icd9_1        icd9_2 icd9_bin_1 icd9_bin_2 icd9_bin
#>    <dbl>  <chr>         <chr>      <dbl>      <dbl>    <dbl>
#> 1      1 414.01        414.01          1          1        1
#> 2      2 411.89          <NA>          1          0        1
#> 3      3   <NA>        410.71          0          1        1
#> 4      4   <NA>          <NA>          0          0        0
#> 5      5   <NA>        410.51          0          1        1
#> 6      6   <NA> 272.0, 410.71          0          1        1

如果您有很多很多这样的列,您可以使用mutate_at()

is_not_na_num <- function(...) as.numeric(Negate(is.na)(...))

# Make up a new column
dat$icd9_3 <- rev(dat$icd9_1)

# To use pattern matching...
data_auto <- dat %>%
  mutate_at(vars(matches("icd9")), funs(bin = is_not_na_num))
data_auto
#> # A tibble: 6 x 7
#>   pat_id icd9_1        icd9_2 icd9_3 icd9_1_bin icd9_2_bin icd9_3_bin
#>    <dbl>  <chr>         <chr>  <chr>      <dbl>      <dbl>      <dbl>
#> 1      1 414.01        414.01   <NA>          1          1          0
#> 2      2 411.89          <NA>   <NA>          1          0          0
#> 3      3   <NA>        410.71   <NA>          0          1          0
#> 4      4   <NA>          <NA>   <NA>          0          0          0
#> 5      5   <NA>        410.51 411.89          0          1          1
#> 6      6   <NA> 272.0, 410.71 414.01          0          1          1

(但要自动化最后的or,您可以使用reduce()...)

bin_any <- data_auto %>%
  select(matches("_bin")) %>%
  purrr::reduce(~ as.numeric(.x | .y))
data_auto$icd9_bin <- bin_any
data_auto["icd9_bin"]
#> # A tibble: 6 x 1
#>   icd9_bin
#>      <dbl>
#> 1        1
#> 2        1
#> 3        1
#> 4        0
#> 5        1
#> 6        1

【讨论】:

  • 谢谢!我选择了模式匹配,因为实际数据是根据特定的医疗条件编码的(即高血压是 htn_icd9_plsthtn_icd9_enc 等)。这个功能将非常有用!我还想分享caret 包中的dummyVar 函数。
【解决方案2】:

根据您的 cmets,if_else() 是一个 dplyr 函数,如果您需要,它可以与 mutate() 很好地配合使用:

dat <- dat %>%
  mutate(icd9_bin_1 = if_else(is.na(dat$icd9_1), "no icd9 dx", "icd9"),
         more...)

【讨论】:

  • 是的,@Phil——这与我目前使用的类似。这需要多个步骤(即每个变量的二进制文件,然后是 either 二进制变量的二进制文件)。我希望有一个解决方案可以跳过第一步并查看一组变量(因为从技术上讲它们是列表?)并返回 1 = at least one icd9 in any of these variables0 = NA in all of these variables
猜你喜欢
  • 2015-05-20
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 2019-03-02
  • 1970-01-01
  • 2022-07-31
  • 1970-01-01
相关资源
最近更新 更多