【问题标题】:Create new column based on multiple conditions in multiple columns根据多列中的多个条件创建新列
【发布时间】:2020-07-11 20:09:07
【问题描述】:

更新以在新变量中包含多个选项:

我正在处理一个凌乱的大数据患者文件(> 4000 万行)。每个患者 (id) 有几行。每行(大致)代表一个带有症状/疾病代码的咨询 (icpc)。我添加了一个新列,其中包含特定条件患者的类别(基于列 icpcicpc2)。

我的原始 data.frame (df) 看起来像这样(这是捏造的数据,id 在我的数据集中更长,我省略了我喜欢删除的不相关列):

    id icpc icpc2 reg.date 
1:  123 D95 F15   19JUN2015 
2:  123 F85       15AUG2016 
3:  332 A01       16MAR2010 
4:  332 A04       20JAN2018
5:  332 K20       20FEB2017
6:  100 B10       01JUN2017 
7:  100 A04       11JAN2008
8:  113 T08       18MAR2018
9:  113 P28       19JAN2017 
10: 113 D95 A01   16JAN2013
11: 113 A04       01MAY2009
12: 551 B12 A01   03APR2011
13: 551 D95       09MAY2015

假设我想在名为“condit”的新列中将D95 和/或A01 的患者分类为“是”(基于icpcicpc2 两列)。以下作品:

cond1 <- c("D95", "A01")
setDT(df)[, condit := ifelse(any(icpc %in% cond1 | icpc2 %in% cond1), "yes","no"), by=id]
df

但现在我想将icpcicpc2 中的几个代码分类到新列condit 中。例如,来自icpcicpc2 的D95 和/或A01 为AA04 和/或T08BB10C 中的condit。注意:A 应该覆盖 B(参见第 4、8 和 11 行),B 应该覆盖 C 等(因为可能 id 可能属于多个类别)。

这是我想要的 data.frame (df):

    id icpc icpc2 reg.date  condit
1:  123 D95 F15   19JUN2015 A
2:  123 F85       15AUG2016 A
3:  332 A01       16MAR2010 A
4:  332 A04       20JAN2018 A
5:  332 K20       20FEB2017 A
6:  100 B10       01JUN2017 C
7:  100 A04       11JAN2008 C
8:  113 T08       18MAR2018 A
9:  113 P28       19JAN2017 A
10: 113 D95 A01   16JAN2013 A
11: 113 A04       01MAY2009 A
12: 551 B12 A01   03APR2011 A
13: 551 D90       09MAY2015 A

任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 添加 'any' 有点帮助... 'if_else(any(icpc %in% c("D95", "A01"), 'yes', 'no'))' not with OR功能
  • 这不是完整的答案,它不允许 R 在两列(icpc 和 icpc2)中找到 A01 或 D95
  • 本次响应者已为您完成,但请在以后发布时按照r标签页面顶部的说明进行操作。

标签: r if-statement data.table bigdata grouping


【解决方案1】:

我认为你应该写:

df.cat <- df %>%
  group_by(id) %>%
  mutate(condit = 
           if_else((icpc %in% c("D95", "A01")) | (icpc2 %in% c("D95", "A01")) ~ 'yes', 'no'))

当有多个选择时,您不应使用==。顺便说一句,我在您的逻辑比较中添加了括号

【讨论】:

    【解决方案2】:

    对于您的大型(> 4000 万行)数据集,data.table 包可能是一个不错的选择:

    library(data.table)
    
    cond1 <- c("D95", "A01")
    setDT(df)[, condit := ifelse(any(icpc %in% cond1 | icpc2 %in% cond1), "yes","no"), by=id]
    df
    

         id icpc icpc2  reg.date condit
     1: 123  D95   F15 19JUN2015    yes
     2: 123  F85       15AUG2016    yes
     3: 332  A01       16MAR2010    yes
     4: 332  A04       20JAN2018    yes
     5: 332  K20       20FEB2017    yes
     6: 100  B10       01JUN2017     no
     7: 100  A04       11JAN2008     no
     8: 113  T08       18MAR2018    yes
     9: 113  P28       19JAN2017    yes
    10: 113  D95   A01 16JAN2013    yes
    11: 113  A04       01MAY2009    yes
    12: 551  B12   A01 03APR2011    yes
    13: 551  D95       09MAY2015    yes
    

    数据

    df <- structure(list(id = c(123L, 123L, 332L, 332L, 332L, 100L, 100L, 
    113L, 113L, 113L, 113L, 551L, 551L), icpc = c("D95", "F85", "A01", 
    "A04", "K20", "B10", "A04", "T08", "P28", "D95", "A04", "B12", 
    "D95"), icpc2 = c("F15", "", "", "", "", "", "", "", "", "A01", 
    "", "A01", ""), reg.date = c("19JUN2015", "15AUG2016", "16MAR2010", 
    "20JAN2018", "20FEB2017", "01JUN2017", "11JAN2008", "18MAR2018", 
    "19JAN2017", "16JAN2013", "01MAY2009", "03APR2011", "09MAY2015"
    )), class = "data.frame", row.names = c(NA, -13L))
    

    编辑:针对多个条件:

    cond1 <- c("D95", "A01") # A
    cond2 <- c("A04", "T08") # B
    cond3 <- "B10"           # C
    
    setDT(df)[, condit := if(any(icpc %in% cond1 | icpc2 %in% cond1)) "A" else 
                             if(any(icpc %in% cond2 | icpc2 %in% cond2)) "B" else
                                if(any(icpc %in% cond3 | icpc2 %in% cond3)) "C" else "", by=id]
    
         id icpc icpc2  reg.date condit
     1: 123  D95   F15 19JUN2015      A
     2: 123  F85       15AUG2016      A
     3: 332  A01       16MAR2010      A
     4: 332  A04       20JAN2018      A
     5: 332  K20       20FEB2017      A
     6: 100  B10       01JUN2017      B
     7: 100  A04       11JAN2008      B
     8: 113  T08       18MAR2018      A
     9: 113  P28       19JAN2017      A
    10: 113  D95   A01 16JAN2013      A
    11: 113  A04       01MAY2009      A
    12: 551  B12   B10 03APR2011      C
    13: 551  D96       09MAY2015      C
    

    数据:(由于未找到“C”条件,因此对原始数据略有修改。

    df <- structure(list(id = c(123L, 123L, 332L, 332L, 332L, 100L, 100L, 
    113L, 113L, 113L, 113L, 551L, 551L), icpc = c("D95", "F85", "A01", 
    "A04", "K20", "B10", "A04", "T08", "P28", "D95", "A04", "B12", 
    "D96"), icpc2 = c("F15", "", "", "", "", "", "", "", "", "A01", 
    "", "B10", ""), reg.date = c("19JUN2015", "15AUG2016", "16MAR2010", 
    "20JAN2018", "20FEB2017", "01JUN2017", "11JAN2008", "18MAR2018", 
    "19JAN2017", "16JAN2013", "01MAY2009", "03APR2011", "09MAY2015"
    )), class = "data.frame", row.names = c(NA, -13L))
    

    在具有 40M 行的数据帧上进行测试: 系统时间(...)

    #    user  system elapsed 
    #  111.11    1.17  111.97 
    

    使用 dplyr:

    # Error: cannot allocate vector of size 274.7 Mb
    # Timing stopped at: 4.19 1.11 5.39
    

    【讨论】:

    • 谢谢,我正在使用 data.table。对于其中一行中包含 A01 或 D95 的所有 id,输出不会给出“是”。请参阅我的问题中的表格。
    • 请更新您的问题以包含此新信息。并尽可能清晰。
    • 查看编辑后的答案。您必须考虑一个人可能属于多个类别的情况。 if 语句的顺序将是关键。如果属于多个类别很重要,那么您必须相应地修改代码。
    【解决方案3】:

    您需要使用any,因为您想为整个组分配值。

    library(dplyr)
    df %>%
      group_by(id) %>%
      mutate(condit = if(any(icpc %in% c("D95", "A01") | icpc2 %in% c("D95", "A01"))) 
                         "yes" else "no")
    

    或者没有if/else 的更快的选择是

    df %>%
       group_by(id) %>%
       mutate(condit = c("no", "yes")[(any(icpc %in% c("D95", "A01") | 
                                            icpc2 %in% c("D95", "A01"))) + 1]) 
    

    【讨论】:

      【解决方案4】:

      检查c(icpc, icpc2) 的任何元素是否在所需的代码中。请注意,结果是一个简单的字符串yesno,所以我们可以只使用if 而不是if_else

      DF %>%
        group_by(id) %>%
        mutate(condit = if (any(c(icpc, icpc2) %in% c("D95", "A01"))) "yes" else "no") %>%
        ungroup
      

      第二种方法是将数据转换为长格式,在这种情况下只有一个 icpc 列(称为value),设置condit,然后转换回宽格式(或者您可能只想离开它是长格式)。最后的select 将列重新排序为与输入相同的顺序,即id 列第一,icpc 列第二,等等。

      library(tidyr)
      DF %>%
        pivot_longer(starts_with("icpc")) %>%
        filter(name != "") %>%
        group_by(id) %>%
        mutate(condit = if (any(value %in% c("D95", "A01"))) "yes" else "no") %>%
        pivot_wider %>%
        select(names(DF))
      

      注意

      假设可重现形式的输入为:

      Lines <- "id icpc icpc2 reg.date 
      123 D95 F15   19JUN2015 
      123 F85       15AUG2016 
      332 A01       16MAR2010 
      332 A04       20JAN2018
      332 K20       20FEB2017
      100 B10       01JUN2017 
      100 A04       11JAN2008
      113 T08       18MAR2018
      113 P28       19JAN2017 
      113 D95 A01   16JAN2013
      113 A04       01MAY2009
      551 B12 A01   03APR2011
      551 D95       09MAY2015"
      L <- readLines(textConnection(Lines))
      L <- sub(" (\\S+) ", ",\\1,", L)
      L <- sub(" +", ",", L)
      DF <- read.csv(text = L, check.names = FALSE, as.is = TRUE, strip.white = TRUE)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-12
        • 2017-01-17
        • 2019-08-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多