【问题标题】:Split a string with varying length in a data table在数据表中拆分具有不同长度的字符串
【发布时间】:2017-01-11 09:31:14
【问题描述】:

我想根据另一列中的部分字符串创建一列。

参考栏遵循一般格式:GB/Ling 31st Dec

我想在这种情况下提取“Ling”这个词,它有不同的长度。

到目前为止,我的方法是:

library(data.table)
d1 <- data.table(MENU_HINT = 
                 c("GB / Ling 31st Dec", "GB / Taun 30th Dec", 
                   "GB / Ayr 19th Dec", "GB / Ayr 9th Nov", 
                   "GB / ChelmC 29th Sep"), 
             Track = c("Ling", "Taun", "Ayr", "Ayr", "ChelmC"))

#remove all the spaces
d1[, Track2 := gsub("[[:space:]]", "", MENU_HINT)]

# get the position of the first digit
d1[, x := as.numeric(regexpr("[[:digit:]]", Track2)[[1]])]

# get the position of the '/'
d1[, y := as.numeric(regexpr("/", Track2))[[1]]]

# use above to extract the Track
d1[, Track2 := substr(Track2, y + 1, x - 1)]

Track 是我期望得到的,Track2 是我从上面的代码中得到的。

这看起来很啰嗦,而且似乎也不起作用,因为 x 和 y 值在整个列中都是相同的。

【问题讨论】:

  • 请展示一个可重现的小例子和预期的输出
  • 查看str_extractstringr的函数。
  • @akrun 道歉,小例子现已添加。
  • 我不会为此使用正则表达式 - 它对于大数据集不会有效。您要查找的单词似乎始终位于第二个空格之后。一个非常简单有效的解决方案可能是d1[, Track2 := tstrsplit(MENU_HINT, " ", fixed = TRUE)[[3]]]
  • @DavidArenburg 感谢大卫,您的回答实际上比我的约 70 万行数据快 2.5 倍。

标签: r regex data.table


【解决方案1】:

我不会为此使用正则表达式 - 它对于大数据集效率不高。您要查找的单词似乎始终位于第二个空格之后。一个非常简单有效的解决方案可能是

d1[, Track2 := tstrsplit(MENU_HINT, " ", fixed = TRUE)[[3]]] 

基准测试

bigDT <- data.table(MENU_HINT = sample(d1$MENU_HINT, 1e6, replace = TRUE))
microbenchmark::microbenchmark("sub: " = sub("\\S+[[:punct:] ]+(\\S+).*", "\\1", bigDT$MENU_HINT),
                               "gsub: " = gsub("^[^/]+/\\s*|\\s+.*$", "", bigDT$MENU_HINT),
                               "tstrsplit: " = tstrsplit(bigDT$MENU_HINT, " ", fixed = TRUE)[[3]])
# Unit: milliseconds
#        expr       min        lq      mean    median        uq      max neval
#       sub:   982.1185  998.6264 1058.1576 1025.8775 1083.1613 1405.051   100
#      gsub:  1236.9453 1262.6014 1320.4436 1305.6711 1339.2879 1766.027   100
# tstrsplit:   385.4785  452.6476  498.8681  470.8281  537.5499 1044.691   100

【讨论】:

    【解决方案2】:

    我们可以使用sub

    d1[, Track2 := sub("\\S+[[:punct:] ]+(\\S+).*", "\\1", MENU_HINT)]
    

    gsub

    d1[, Track2 := gsub("^[^/]+/\\s*|\\s+.*$", "", MENU_HINT)]
    d1
    #              MENU_HINT  Track Track2
    #1:   GB / Ling 31st Dec   Ling   Ling
    #2:   GB / Taun 30th Dec   Taun   Taun
    #3:    GB / Ayr 19th Dec    Ayr    Ayr
    #4:     GB / Ayr 9th Nov    Ayr    Ayr
    #5: GB / ChelmC 29th Sep ChelmC ChelmC
    

    【讨论】:

    • 感谢您的快速回复。 'sub' 似乎比我的数据中的 2 稍快。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 2021-09-10
    • 2018-05-27
    • 1970-01-01
    • 1970-01-01
    • 2020-05-26
    相关资源
    最近更新 更多