【问题标题】:I am searching an optimal way to change variable categories in dummy variables我正在寻找一种更改虚拟变量中的变量类别的最佳方法
【发布时间】:2021-12-28 09:04:03
【问题描述】:

我有一些患者在不同的时间接受不同的治疗。 我想将他们接受的治疗更改为一个二进制变量,如果患者至少接受过一次药物,则取值为 1,如果他们从未接受过药物,则取值为 0。

我设法做到了这一点,但方法很繁琐,使用几十种不同类型的药物可能很难。

我想优化我的代码,主要是避免一一创建所有与药物相关的二进制变量。

id<-c(rep("A",7),rep("B",4))
medoc<-c("par","mor","mor","par","sed","sed",
         "sed","cur","sed","cur","sed")

mydata<-data.frame(id,medoc)

mydata2<-mydata%>%group_by(id)%>%
  mutate(medoc_str=paste(unique(medoc),collapse  = " "))%>%
  distinct(id,.keep_all = TRUE)

mydata2$par<-NA
mydata2$mor<-NA
mydata2$sed<-NA
mydata2$cur<-NA

mydata2$par<-ifelse(
  grepl("par",mydata2$medoc_str)==TRUE,1,0
)

mydata2$mor<-ifelse(
  grepl("mor",mydata2$medoc_str)==TRUE,1,0
)

mydata2$sed<-ifelse(
  grepl("sed",mydata2$medoc_str)==TRUE,1,0
)

mydata2$cur<-ifelse(
  grepl("cur",mydata2$medoc_str)==TRUE,1,0
)

【问题讨论】:

    标签: r dummy-variable grepl


    【解决方案1】:

    如果我理解的话,您想对变量进行虚拟化。 我们也可以使用tidyr::pivot_wider 来做到这一点,但我真的很喜欢使用特定的库来轻松地做到这一点。我喜欢fastDummies 包:

    library(fastDummies)
    
    dummy_cols(mydata, select_columns = 'medoc')
    
       id medoc medoc_cur medoc_mor medoc_par medoc_sed
    1   1   par         0         0         1         0
    2   1   mor         0         1         0         0
    3   1   mor         0         1         0         0
    4   1   par         0         0         1         0
    5   1   sed         0         0         0         1
    6   1   sed         0         0         0         1
    7   1   sed         0         0         0         1
    8   2   cur         1         0         0         0
    9   2   sed         0         0         0         1
    10  2   cur         1         0         0         0
    11  2   sed         0         0         0         1
    

    这是pivot_wider的答案:

    library(tidyr)
    library(dplyr)
    mydata %>% mutate(index = row_number()) %>%
      pivot_wider(names_from = medoc,
                  values_from = medoc,
                  values_fn = \(x) +!is.na(x),
                  values_fill = 0)
    

    【讨论】:

    • 后一种解决方案给了我一个错误 - 是pivot_wider的新版本的反斜杠部分吗?相比之下,values_fn = function(x) +!is.na(x) 可以工作
    • \(x) x 是 R 4.0 的基础 R lambda 函数。你用的是什么版本的@Chris?
    【解决方案2】:

    类似于@Guedes 的解决方案,但具有不同的values_fn

    library(dplyr)
    library(tidyr)
    
    mydata %>%
      mutate(row = row_number()) %>%
      pivot_wider(names_from = medoc, values_from = medoc,
                  values_fn = function(x) 1, values_fill = 0) %>%
      select(-row)
    # A tibble: 11 x 5
          id   par   mor   sed   cur
       <dbl> <dbl> <dbl> <dbl> <dbl>
     1     1     1     0     0     0
     2     1     0     1     0     0
     3     1     0     1     0     0
     4     1     1     0     0     0
     5     1     0     0     1     0
     6     1     0     0     1     0
     7     1     0     0     1     0
     8     2     0     0     0     1
     9     2     0     0     1     0
    10     2     0     0     0     1
    11     2     0     0     1     0
    

    【讨论】:

    • 确实,这个 values_fn 版本简单一些。正如我在上面的评论中所说,我会在 R 版本 4 或更高版本中使用更简单的版本,如 values_fn = \(x) 1
    • 谢谢你,太好了
    【解决方案3】:

    在最后的注释中使用 mydata 并假设您希望每个 id 有一行,并使用二进制列指示 medoc 的哪些值存在 (1) 或不存在 (0),我们可以像这样使用 table。 (如果您想要计数而不是存在/不存在,请省略 pmin。)

    pmin(table(mydata), 1)
    ##    medoc
    ## id  cur mor par sed
    ##  A   0   1   1   1
    ##  B   1   0   0   1
    

    或作为数据框并添加 medoc_str

    library(dplyr)
    library(tibble)
    
    mydata %>%
      table %>%
      pmin(1) %>%
      as.data.frame.matrix %>%
      rownames_to_column(var = "id") %>%
      group_by(id) %>%
      mutate(medoc_str = paste(names(cur_data())[c_across() == 1], collapse = " ")) %>%
      ungroup
    ## # A tibble: 2 x 6
    ##   id      cur   mor   par   sed medoc_str  
    ##   <chr> <dbl> <dbl> <dbl> <dbl> <chr>      
    ## 1 A         0     1     1     1 mor par sed
    ## 2 B         1     0     0     1 cur sed    
    

    注意

    修改 mydata 以使用更好的 id。

    id <- c(rep("A", 7), rep("B", 4))
    medoc <- c("par", "mor", "mor", "par", "sed", "sed",
             "sed", "cur", "sed", "cur", "sed")
    
    mydata <- data.frame(id, medoc)
    

    我的数据看起来像这样。

    > mydata
       id medoc
    1   A   par
    2   A   mor
    3   A   mor
    4   A   par
    5   A   sed
    6   A   sed
    7   A   sed
    8   B   cur
    9   B   sed
    10  B   cur
    11  B   sed
    

    【讨论】:

    • 非常好的脚本,但是患者的初始ID丢失了
    • 哎呀,你是对的。我不清楚。谢谢
    • 在最后的Note里修改了id,把它拿出来,并对代码做了相应的修复。
    猜你喜欢
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-18
    • 2012-06-12
    相关资源
    最近更新 更多