【问题标题】:Aggregating by a substring of column按列的子字符串聚合
【发布时间】:2018-08-02 14:55:54
【问题描述】:

考虑 R 中的以下数据框:

  TYPE    VARIAVEL                           VALOR               

  A       OPER_RELAC_VARIAVEL1                100
  A       OPER_RELAC_VARIAVEL2                200
  A       OPER_RELAC_VARIAVEL3                300
  B       OPER_RELAC_VARIAVEL1                100
  B       OPER_RELAC_VARIAVEL2                200
  B       OPER_RELAC_VARIAVEL3                300
  A       CLI_RELAC_VARIAVEL1                 450
  A       CLI_RELAC_VARIAVEL2                 320
  A       CLI_RELAC_VARIAVEL3                 110

我想根据VARIAVELTYPE 的根来获取每个VALOR 的相关性。我没有以VARIAVEL 为根的列,但它会在第二个_ 之前出现(在此示例中为OPER_RELACCLI_RELAC)。

预期结果是:

  TYPE    VARIAVEL                           VALOR           RELEVANCE    

  A       OPER_RELAC_VARIAVEL1                100            0.167
  A       OPER_RELAC_VARIAVEL2                200            0.333
  A       OPER_RELAC_VARIAVEL3                300            0.500
  B       OPER_RELAC_VARIAVEL1                100            0.167
  B       OPER_RELAC_VARIAVEL2                200            0.333
  B       OPER_RELAC_VARIAVEL3                300            0.500
  A       CLI_RELAC_VARIAVEL1                 450            0.511
  A       CLI_RELAC_VARIAVEL2                 320            0.364
  A       CLI_RELAC_VARIAVEL3                 110            0.125

因为,例如,对于类型 A 和根变量 CLI_RELAC,450 代表总数的 51.1%。


我已经完成了这个命令序列:

1) 使用库stringr 生成带有根变量的列

dados$VARIAVEL_MAE <- str_match(dados$VARIAVEL, "^([^_]+[_][^_]+)")[,2]

感谢R:how to get grep to return the match, rather than the whole string

2) 在一个新的数据框中总结这个新列聚合的总数

TOTAIS <- aggregate(VALOR ~ Type + VARIAVEL_MAE, data = dados, sum)
names(TOTAIS) <- c('Type', 'VARIAVEL_MAE', 'TOTAL')

3) 使用建议的 here 合并这两个数据帧

dados <- merge(TOTAIS, dados, by = c('Type', 'VARIAVEL_MAE'))
dados$RELEVANCIA <- dados$VALOR / dados$TOTAL;

有没有更聪明的方法或者我确实需要所有这些步骤?

我的问题是因为在 R 中,我所做的一切总是可以被更快更小的东西所取代。

【问题讨论】:

    标签: r merge aggregate stringr


    【解决方案1】:

    在 OP 的示例中,我们可以拆分 _ 而不是使用正则表达式:

    library(data.table)
    setDT(DT)
    
    DT[, paste0("vnome", 1:3) := tstrsplit(VARIAVEL, "_")]
    DT[, z := VALOR/sum(VALOR), by=.(TYPE, vnome1, vnome2)]
    
       TYPE             VARIAVEL VALOR vnome1 vnome2    vnome3         z
    1:    A OPER_RELAC_VARIAVEL1   100   OPER  RELAC VARIAVEL1 0.1666667
    2:    A OPER_RELAC_VARIAVEL2   200   OPER  RELAC VARIAVEL2 0.3333333
    3:    A OPER_RELAC_VARIAVEL3   300   OPER  RELAC VARIAVEL3 0.5000000
    4:    B OPER_RELAC_VARIAVEL1   100   OPER  RELAC VARIAVEL1 0.1666667
    5:    B OPER_RELAC_VARIAVEL2   200   OPER  RELAC VARIAVEL2 0.3333333
    6:    B OPER_RELAC_VARIAVEL3   300   OPER  RELAC VARIAVEL3 0.5000000
    7:    A  CLI_RELAC_VARIAVEL1   450    CLI  RELAC VARIAVEL1 0.5113636
    8:    A  CLI_RELAC_VARIAVEL2   320    CLI  RELAC VARIAVEL2 0.3636364
    9:    A  CLI_RELAC_VARIAVEL3   110    CLI  RELAC VARIAVEL3 0.1250000
    

    在更一般的情况下,OP 提到“第二个 _ 之前的所有内容”,我们可以使用另一个问答中的 @akrun's approach(假设 VARIAVEL 不包含空格):

    DT[, c("vroot", "vseq") := 
      tstrsplit(sub('(^[^_]+_[^_]+)_(.*)$', '\\1 \\2', VARIAVEL), ' ')]
    DT[, z := VALOR/sum(VALOR), by=.(TYPE, vroot)]
    
       TYPE             VARIAVEL VALOR      vroot      vseq         z
    1:    A OPER_RELAC_VARIAVEL1   100 OPER_RELAC VARIAVEL1 0.1666667
    2:    A OPER_RELAC_VARIAVEL2   200 OPER_RELAC VARIAVEL2 0.3333333
    3:    A OPER_RELAC_VARIAVEL3   300 OPER_RELAC VARIAVEL3 0.5000000
    4:    B OPER_RELAC_VARIAVEL1   100 OPER_RELAC VARIAVEL1 0.1666667
    5:    B OPER_RELAC_VARIAVEL2   200 OPER_RELAC VARIAVEL2 0.3333333
    6:    B OPER_RELAC_VARIAVEL3   300 OPER_RELAC VARIAVEL3 0.5000000
    7:    A  CLI_RELAC_VARIAVEL1   450  CLI_RELAC VARIAVEL1 0.5113636
    8:    A  CLI_RELAC_VARIAVEL2   320  CLI_RELAC VARIAVEL2 0.3636364
    9:    A  CLI_RELAC_VARIAVEL3   110  CLI_RELAC VARIAVEL3 0.1250000
    

    数据:

    DT = structure(list(TYPE = c("A", "A", "A", "B", "B", "B", "A", "A", 
    "A"), VARIAVEL = c("OPER_RELAC_VARIAVEL1", "OPER_RELAC_VARIAVEL2", 
    "OPER_RELAC_VARIAVEL3", "OPER_RELAC_VARIAVEL1", "OPER_RELAC_VARIAVEL2", 
    "OPER_RELAC_VARIAVEL3", "CLI_RELAC_VARIAVEL1", "CLI_RELAC_VARIAVEL2", 
    "CLI_RELAC_VARIAVEL3"), VALOR = c(100L, 200L, 300L, 100L, 200L, 
    300L, 450L, 320L, 110L)), .Names = c("TYPE", "VARIAVEL", "VALOR"
    ), row.names = c(NA, -9L), class = "data.frame")
    

    【讨论】:

    • Plus 1,但这对于正则表达式来说似乎并不特别复杂。难道我们不能做类似by=.(TYPE, sub("(.*_.*)_.*", "\\1", VARIAVEL)) 或类似的事情吗?
    • 所有时候我都对 R 中的事情比我想象的更简单感到惊讶......谢谢!!!!但我们必须考虑的是变量可以通过CLI_RELAC_PART1_PART2
    • @a5c 是的,在 Nizam 的评论中,正则表达式也会更有效。我将添加您的或类似的内容,请稍等。旁注:我喜欢在数据处理的早期和最早期做一次正则表达式,所以我会创建一个新的 col,而不是在 by= 中即时进行。
    猜你喜欢
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    • 1970-01-01
    • 2020-12-17
    • 2019-03-03
    • 2015-07-27
    • 1970-01-01
    相关资源
    最近更新 更多