在R中使用Stringr和regex从文本中提取数字

时间:2018-09-24 19:36:25

标签: r regex stringr

我遇到一个问题,我试图从包含文本和数字的字符串中提取数字,然后创建两个新列来显示数字的最小值和最大值。

例如,我有一列和一串数据,像这样:

Text
Section 12345.01 to section 12345.02

我想从“文本”列中的数据创建两个新列,如下所示:

Min        Max   
12345.01   12345.02

我在regex中使用dplyr和stringr,但是regex仅提取模式的第一个匹配项(第一个数字)。

df%>%dplyr::mutate(SectionNum = stringr::str_extract(Text, "\\d+.\\d+"))

如果我尝试使用stringr::str_extract_all函数。似乎提取了两种模式的出现,但它在小标题中创建了一个列表,我发现这是一个真正的麻烦。因此,我停留在第一步,只是尝试将数字放入自己的栏中。

有人可以推荐最有效的方法吗?理想情况下,我想从字符串中提取数字,将其转换为数字as.numeric,然后运行min()max()函数。

3 个答案:

答案 0 :(得分:3)

使用extract中的tidyrextract将每个正则表达式捕获组转换为自己的列。 convert = TRUE的方便之处在于它可以将结果列强制为最佳格式。如果我们想保留原始列,可以使用remove = FALSE。最后一个mutate是可选的,以确保提取的第一个数字确实是最小值:

library(tidyr)
library(purrr)

df %>%
  extract(Text, c("Min", "Max"), "([\\d.]+)[^\\d.]+([\\d.]+)", convert = TRUE) %>%
  mutate(Min = pmap_dbl(., min),
         Max = pmap_dbl(., max))

输出:

       Min      Max
1 12345.02 12345.03

数据:

df <- structure(list(Text = structure(1L, .Label = "Section 12345.03 to section 12345.02", class = "factor")), class = "data.frame", row.names = c(NA, 
-1L), .Names = "Text")

答案 1 :(得分:3)

使用其他tidyverse工具,您可以通过unnest列出列表列并使用group_bysummarise语义(更多{{1} }),或者您可以按原样处理list-col并使用dplyr从每一行中提取最大值和最小值(更多map_dbl方式)。我的基准测试purrrmap_dblunnest快7倍,比dplyr快15%,尽管这只是一行。

extract

reprex package(v0.2.0)于2018-09-24创建。

答案 2 :(得分:1)

已经有答案说明如何按照问题中的要求完成最终目标,但是只是为了解决如何使用stringr包找到第一个或第二个比赛的问题,您可以使用str_match函数,并通过参考str_match列指定您感兴趣的特定匹配项。

library(stringr)

Text <- "Section 12345.01 to section 12345.02"

str_match(Text, "^[^0-9.]*([0-9.]*)[^0-9.]*([0-9.]*)[^0-9.]*$")[2]
#> [1] "12345.01"
str_match(Text, "^[^0-9.]*([0-9.]*)[^0-9.]*([0-9.]*)[^0-9.]*$")[3]
#> [1] "12345.02"

reprex package(v0.2.0)于2018-09-24创建。