【问题标题】:how to match values in columns by group or within category (groupwise) with other column(having multiple values) in same dataframe in R如何在R中的同一数据框中按组或类别(按组)与其他列(具有多个值)匹配列中的值
【发布时间】:2018-11-10 22:08:42
【问题描述】:

所以,我在 R 中有如下数据表:

Claim failure Part code matchcode
23     F1     P1    A   B,A,C
23     F1     P1    D   B,A,C
23     F2     P2    D   B,A,C
23     F2     P2    E   B,A,C
45     F1     P4    X   Y,Z,X
45     F1     P4    Y   Y,Z,X
45     F1     P4    A   Y,Z,X
45     F1     P1    F   Y,Z,X
45     F1     P1    H   Y,Z,X

所以这里的想法是针对每个组(索赔、失败和部分),如果“代码”中的“任何”代码与“匹配代码”列中的代码列表匹配,那么组应该将匹配列设置为 True。

所以预期的输出应该如下:

Claim failure Part Match 
23     F1     P1    TRUE   
23     F2     P2    FALSE  
45     F1     P4    TRUE
45     F1     P1    FALSE

此 data.table 的大小很大,因此需要优化的解决方案。 请帮忙:)

【问题讨论】:

  • 如果你想向量化/优化正则表达式操作,总是使用 stringi 包。这将远远快于任何替代方案(至少我知道)。出于您的目的,我只会做library(stringi) ; DT[, .(Match = any(stri_detect_fixed(matchcode, code))), by = .(Claim, failure, Part)]。我也会做一些搜索,因为矢量化 grepl 已经讨论过很多次了

标签: r data.table


【解决方案1】:

...以及使用data.table的解决方案。

library(data.table)
grepl_v <- Vectorize(grepl)
DT[, .(Match = any(grepl_v(code, matchcode))), by = .(Claim, failure, Part)]
#   Claim failure Part Match
#1:    23      F1   P1  TRUE
#2:    23      F2   P2 FALSE
#3:    45      F1   P4  TRUE
#4:    45      F1   P1 FALSE

数据

DT <- fread("Claim failure Part code matchcode
23     F1     P1    A   B,A,C
23     F1     P1    D   B,A,C
23     F2     P2    D   B,A,C
23     F2     P2    E   B,A,C
45     F1     P4    X   Y,Z,X
45     F1     P4    Y   Y,Z,X
45     F1     P4    A   Y,Z,X
45     F1     P1    F   Y,Z,X
45     F1     P1    H   Y,Z,X")

【讨论】:

    【解决方案2】:

    这是dplyr 解决方案。

    library(dplyr)
    
    dat %>%
      rowwise() %>%
      mutate(Match = grepl(code, matchcode)) %>%
      group_by(Claim, failure, Part) %>%
      mutate(Match = any(Match)) %>%
      select(-code, -matchcode) %>%
      unique
    ## A tibble: 4 x 4
    ## Groups:   Claim, failure, Part [4]
    #  Claim failure Part  Match
    #  <int> <fct>   <fct> <lgl>
    #1    23 F1      P1    TRUE 
    #2    23 F2      P2    FALSE
    #3    45 F1      P4    TRUE 
    #4    45 F1      P1    FALSE
    #Warning message:
    #Grouping rowwise data frame strips rowwise nature 
    

    不要担心警告,它只是告诉您在grep'ing rowwise 之后,管道按某些变量分组,因此不再逐行处理。

    数据。

    dat <- read.table(text = "
    Claim failure Part code matchcode
    23     F1     P1    A   B,A,C
    23     F1     P1    D   B,A,C
    23     F2     P2    D   B,A,C
    23     F2     P2    E   B,A,C
    45     F1     P4    X   Y,Z,X
    45     F1     P4    Y   Y,Z,X
    45     F1     P4    A   Y,Z,X
    45     F1     P1    F   Y,Z,X
    45     F1     P1    H   Y,Z,X                  
    ", header = TRUE)
    

    【讨论】:

      【解决方案3】:

      base解决方案:

      d$match <- apply(d, 1, function(x) { return(grepl(x[['code']], x['matchcode']))})
      
      # Claim   failure Part code matchcode match
      # 1    23      F1   P1    A     B,A,C     1
      # 2    23      F1   P1    D     B,A,C     0
      # 3    23      F2   P2    D     B,A,C     0
      # 4    23      F2   P2    E     B,A,C     0
      # 5    45      F1   P4    X     Y,Z,X     1
      # 6    45      F1   P4    Y     Y,Z,X     1
      # 7    45      F1   P4    A     Y,Z,X     0
      # 8    45      F1   P1    F     Y,Z,X     0
      # 9    45      F1   P1    H     Y,Z,X     0
      

      此答案的原始版本使用grep();感谢markus 建议grepl()

      【讨论】:

        猜你喜欢
        • 2016-12-11
        • 1970-01-01
        • 1970-01-01
        • 2018-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多