使用R中的stringr和regex从文本中提取数字

Rya*_*yan 5 regex r stringr

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

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

Text
Section 12345.01 to section 12345.02
Run Code Online (Sandbox Code Playgroud)

我想从 Text 列中的数据创建两个新列,如下所示:

Min        Max   
12345.01   12345.02
Run Code Online (Sandbox Code Playgroud)

我将 dplyr 和 stringr 与正则表达式一起使用,但正则表达式仅提取模式的第一次出现(第一个数字)。

df%>%dplyr::mutate(SectionNum = stringr::str_extract(Text, "\\d+.\\d+"))
Run Code Online (Sandbox Code Playgroud)

如果我尝试使用该stringr::str_extract_all功能。它似乎提取了模式的两个出现,但它在小标题中创建了一个列表,我发现这是一个真正的麻烦。所以我坚持第一步,只是想把数字放到他们自己的列中。

谁能推荐最有效的方法来做到这一点?理想情况下,我想从字符串中提取数字,将它们转换为数字as.numeric,然后运行min()max()运行。

avi*_*seR 6

随着extracttidyrextract将每个正则表达式捕获组变成它自己的列。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))
Run Code Online (Sandbox Code Playgroud)

输出:

       Min      Max
1 12345.02 12345.03
Run Code Online (Sandbox Code Playgroud)

数据:

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")
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案!(+1)。首先我看到了 `tidyr::extract()` 函数,它很棒。虽然,我会说如果最小值和最大值不是第一次和第二次匹配,这可能会遇到问题。 (3认同)

Cal*_*You 5

使用其他一些tidyverse工具,您可以通过unnesting list-column 并使用group_byandsummarise语义(更多dplyr方式)来解决这个问题,或者您可以按原样处理 list-col 并用于map_dbl从每一行中提取最大值和最小值(更多的purrr方式)。我的基准测试map_dblunnest和快约 7 倍,比 快dplyr约 15% extract,尽管这仅在一行上。

library(tidyverse)
df <- tibble(
  Text = c("Section 12345.01 to section 12345.02")
)

df %>%
  mutate(SectionNum = str_extract_all(Text, "\\d+\\.\\d+")) %>%
  unnest %>%
  group_by(Text) %>%
  summarise(min = min(as.numeric(SectionNum)), max = max(as.numeric(SectionNum)))
#> # A tibble: 1 x 3
#>   Text                                    min    max
#>   <chr>                                 <dbl>  <dbl>
#> 1 Section 12345.01 to section 12345.02 12345. 12345.

df %>%
  mutate(
    SectionNum = str_extract_all(Text, "\\d+\\.\\d+"),
    min = map_dbl(SectionNum, ~ min(as.numeric(.x))),
    max = map_dbl(SectionNum, ~ max(as.numeric(.x)))
  )
#> # A tibble: 1 x 4
#>   Text                                 SectionNum    min    max
#>   <chr>                                <list>      <dbl>  <dbl>
#> 1 Section 12345.01 to section 12345.02 <chr [2]>  12345. 12345.
Run Code Online (Sandbox Code Playgroud)

reprex 包(v0.2.0)于 2018 年 9 月 24 日创建。