【问题标题】:Regular expression matching inside dplyrdplyr 中的正则表达式匹配
【发布时间】:2015-09-25 01:03:19
【问题描述】:

在回复this question,时我写了如下代码:

df <- data.frame(Call_Num = c("HV5822.H4 C47 Circulating Collection, 3rd Floor", "QE511.4 .G53 1982 Circulating Collection, 3rd Floor", "TL515 .M63 Circulating Collection, 3rd Floor", "D753 .F4 Circulating Collection, 3rd Floor", "DB89.F7 D4 Circulating Collection, 3rd Floor"))

require(stringr)

matches = str_match(df$Call_Num, "([A-Z]+)(\\d+)\\s*\\.")
df2 <- data.frame(df, letter=matches[,2], number=matches[,3])

现在我的问题是:有没有一种简单的方法可以将最后两行合并为一个dplyr 调用,大概使用mutate()?或者,我也对do() 的解决方案感兴趣。对于 mutate() 方法,由于我们要提取 2 个组,我将采用一种解决方案,使用不同的正则表达式调用 str_match() 两次,每个所需的组一个。

编辑:澄清一下,我在这里看到的主要挑战是str_match 返回一个矩阵,我想知道如何在mutate()do() 中处理它。我对使用其他提取信息的方法解决原始问题不感兴趣。已经给出了很多这样的解决方案here.

【问题讨论】:

    标签: regex r dplyr stringr


    【解决方案1】:

    您可以使用 tidyr 包中的 extract() 执行此操作:

    extract(df, Call_Num, into = c("letter", "number"), regex = "([A-Z]+)(\\d+)\\s*\\.", remove = FALSE)
    
                                                 Call_Num letter number
    1     HV5822.H4 C47 Circulating Collection, 3rd Floor     HV   5822
    2 QE511.4 .G53 1982 Circulating Collection, 3rd Floor     QE    511
    3        TL515 .M63 Circulating Collection, 3rd Floor     TL    515
    4          D753 .F4 Circulating Collection, 3rd Floor      D    753
    5        DB89.F7 D4 Circulating Collection, 3rd Floor     DB     89
    

    它不是 dplyr,但正如上面链接的 CRAN 页面所述,tidyr“专为数据整理(不是一般的重塑或聚合)而设计,并且与 dplyr 数据管道配合得很好。”

    【讨论】:

    • 谢谢。不过,这并没有解决问题的主要问题。我的问题不是解决提取信息的问题,而是如何处理使用mutate(或do)时返回矩阵的函数。
    【解决方案2】:

    你可以试试do

    df %>% 
      do(data.frame(., str_match(.$Call_Num,  "([A-Z]+)(\\d+)\\s*\\.")[,-1],
                                  stringsAsFactors=FALSE)) %>%
      rename_(.dots=setNames(names(.)[-1],c('letter', 'number')))
    #                                             Call_Num letter number
    #1     HV5822.H4 C47 Circulating Collection, 3rd Floor     HV   5822
    #2 QE511.4 .G53 1982 Circulating Collection, 3rd Floor     QE    511
    #3        TL515 .M63 Circulating Collection, 3rd Floor     TL    515
    #4          D753 .F4 Circulating Collection, 3rd Floor      D    753
    #5        DB89.F7 D4 Circulating Collection, 3rd Floor     DB     89
    

    或者正如@SamFirke 评论的那样,重命名列也可以使用

      ---                                    %>%
     setNames(., c(names(.)[1], "letter", "number"))
    

    【讨论】:

    • 最后一行也可以是简单的setNames(., c(names(.)[1], "letter", "number"))
    猜你喜欢
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-30
    • 2011-05-01
    相关资源
    最近更新 更多