【问题标题】:R - Extract strings based on patternR - 根据模式提取字符串
【发布时间】:2018-01-14 05:52:26
【问题描述】:

我有一个矢量数据(这是数据框中的一列):

 [1] "Tue 12-14 (w1-6, CLB 6)"           "Mon 18-20 (w1-6, ColomboThC)"      "Thu 14-16 (w1-6,7-9,10-12, CLB 8)"
 [4] "Fri 13 (w2-9,10-13, Law 388)"      "Fri 14 (w2-9,10-13, Sqhouse206)"   "Fri 15 (w2-9,10-13, Sqhouse115)"  
 [7] "Thu 17 (w2-9,10-13, Block G16)"    "Thu 18 (w2-9,10-13, Block G16)"    "Mon 10 (w2-9,10-13, AinswthG01)"  
[10] "Mon 11 (w2-9,10-13, Sqhouse203)"   "Mon 12 (w2-9,10-13, Sqhouse206)"   "Mon 13 (w2-9,10-13, BUS 114)"     
[13] "Mon 16 (w2-9,10-13, Gold G03)"     "Mon 17 (w2-9,10-13, Quad G047)"    "Mon 20 (w2-9,10-13, Col LG02)"    
[16] "Tue 17 (w2-9,10-13, Quad 1001)"    "Tue 18 (w2-9,10-13, Quad 1001)"    "Tue 19 (w2-9,10-13, Quad 1001)"   
[19] "Tue 20 (w2-9,10-13)"               "Wed 10 (w2-9,10-13, Quad 1046)"    "Wed 11 (w2-9,10-13, Quad 1046)"   
[22] "Wed 12 (w2-9,10-13, Quad 1046)"    "Wed 13 (w2-9,10-13, Quad G046)"

我想根据模式提取字符串,因此作为示例,向量的第一个元素的预期输出将是:

"Tue" "12-14"  "1-6" "CLB 6"

第三个元素的输出示例为:

 "Thu" "14-16" c("1-6","7-9","10-12") "CLB 8"

c("1-6","7-9","10-12") 是一个列表。

(请注意,每一个都将作为新列附加到我的数据框中。)

我正在考虑使用gsub 来提取字符串的每个部分。还有其他我可以使用的功能吗?

非常感谢任何建议:)

【问题讨论】:

  • 我想我也可以找到使用 grep 提取此内容的方法,但希望与至少发布过代码并自己尝试过一次的人合作,这是 stackoverflow 最有效的方法正常工作:)
  • ?strsplit 通常对这类事情也有帮助。指定分割文本段的内容。 “(w”或“)”或“,”看起来像。将它们中的每一个放入strsplit 中,就像strsplit(x, "\\s+\\(w|\\)|,\\s+") 一样,你就成功了。

标签: r regex dataframe extract


【解决方案1】:

我们可以试试tidyverse的函数:

library(tidyverse)
str_split_fixed(vec, pattern = " ", n = 3) %>% 
  as.data.frame() %>%
  mutate(V3 = str_sub(V3,3,-2)) %>%
  separate(V3, c("V3", "V4"), sep = ", ")

代码如下:

  1. 将向量 vec 用空格分割成 3 列,并将其强制转换为数据框。
  2. 从第 3 列中提取字符串以排除左括号和右括号以及“w”。
  3. ", "分隔第三列。

输出示例:

   V1    V2            V3         V4
1 Tue 12-14           1-6      CLB 6
2 Mon 18-20           1-6 ColomboThC
3 Thu 14-16 1-6,7-9,10-12      CLB 8

【讨论】:

    【解决方案2】:

    使用末尾注释中的输入x

    • 用分号替换每个字符串中的第一个空格,
    • 用分号替换下一个空格及其后面的两个字符,
    • 用分号替换下一个逗号空格
    • 删除最后一个字符
    • 将其读入以分号分隔字段的数据帧
    • 使用逗号将第 3 列拆分为字符向量列表 -- 如果您更喜欢使用字符串而不是列为第 3 列,请忽略此步骤

    它只使用单独的简单步骤,没有包。

    y <- x
    y <- sub(" ", ";", y)
    y <- sub(" ..", ";", y)
    y <- sub(", ", ";", y)
    y <- sub(".$", "", y)
    DF <- read.table(text = y, sep = ";", as.is = TRUE, fill = NA)
    DF[[3]] <- strsplit(DF[[3]], ",")
    

    给予:

    > DF
        V1    V2              V3         V4
    1  Tue 12-14             1-6      CLB 6
    2  Mon 18-20             1-6 ColomboThC
    3  Thu 14-16 1-6, 7-9, 10-12      CLB 8
    4  Fri    13      2-9, 10-13    Law 388
    5  Fri    14      2-9, 10-13 Sqhouse206
    6  Fri    15      2-9, 10-13 Sqhouse115
    7  Thu    17      2-9, 10-13  Block G16
    8  Thu    18      2-9, 10-13  Block G16
    9  Mon    10      2-9, 10-13 AinswthG01
    10 Mon    11      2-9, 10-13 Sqhouse203
    11 Mon    12      2-9, 10-13 Sqhouse206
    12 Mon    13      2-9, 10-13    BUS 114
    13 Mon    16      2-9, 10-13   Gold G03
    14 Mon    17      2-9, 10-13  Quad G047
    15 Mon    20      2-9, 10-13   Col LG02
    16 Tue    17      2-9, 10-13  Quad 1001
    17 Tue    18      2-9, 10-13  Quad 1001
    18 Tue    19      2-9, 10-13  Quad 1001
    19 Tue    20      2-9, 10-13           
    20 Wed    10      2-9, 10-13  Quad 1046
    21 Wed    11      2-9, 10-13  Quad 1046
    

    可以用这一行替换前 4 行代码,在这种情况下,总共可以减少到只有 4 行代码。

    y <- Reduce(function(x, pat) sub(pat, ";", x), init = x, c(" ", " ..", ", "))
    

    注意:可重现形式的输入x是:

    x <- c("Tue 12-14 (w1-6, CLB 6)", "Mon 18-20 (w1-6, ColomboThC)", 
    "Thu 14-16 (w1-6,7-9,10-12, CLB 8)", "Fri 13 (w2-9,10-13, Law 388)", 
    "Fri 14 (w2-9,10-13, Sqhouse206)", "Fri 15 (w2-9,10-13, Sqhouse115)", 
    "Thu 17 (w2-9,10-13, Block G16)", "Thu 18 (w2-9,10-13, Block G16)", 
    "Mon 10 (w2-9,10-13, AinswthG01)", "Mon 11 (w2-9,10-13, Sqhouse203)", 
    "Mon 12 (w2-9,10-13, Sqhouse206)", "Mon 13 (w2-9,10-13, BUS 114)", 
    "Mon 16 (w2-9,10-13, Gold G03)", "Mon 17 (w2-9,10-13, Quad G047)", 
    "Mon 20 (w2-9,10-13, Col LG02)", "Tue 17 (w2-9,10-13, Quad 1001)", 
    "Tue 18 (w2-9,10-13, Quad 1001)", "Tue 19 (w2-9,10-13, Quad 1001)", 
    "Tue 20 (w2-9,10-13)", "Wed 10 (w2-9,10-13, Quad 1046)", "Wed 11 (w2-9,10-13, Quad 1046)", 
    "Wed 12 (w2-9,10-13, Quad 1046)", "Wed 13 (w2-9,10-13, Quad G046)"
    

    【讨论】:

      【解决方案3】:

      基本功能即可,无需导入其他包。 tidyverse 很棒,但对于这个来说有点大,

      x=c("Thu 18 (w2-9,10-13, Block G16)","Mon 18-20 (w1-6, ColomboThC)")
      do.call(rbind,lapply(x,function(i){
        y=strsplit(i,' \\(')[[1]]
        y[2]=gsub('\\)','',y[2])
        out1=strsplit(y[1],' ')[[1]]
        out2=strsplit(y[2],', ')[[1]]
        listpart=grepl('-',out2)
        do.call(cbind,c(out1,list(out2[listpart]),out2[!listpart]))
      }))
      

      输出将是:

               [,1]  [,2]    [,3]         [,4]        
      [1,] "Thu" "18"    "w2-9,10-13" "Block G16" 
      [2,] "Mon" "18-20" "w1-6"       "ColomboThC"
      

      【讨论】:

        猜你喜欢
        • 2013-06-17
        • 2023-03-08
        • 2021-09-25
        • 1970-01-01
        • 1970-01-01
        • 2021-04-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-10
        相关资源
        最近更新 更多