我有一个问题,我试图从包含文本和数字的字符串中提取数字,然后创建两个新列,显示数字的最小值和最大值。
例如,我有一列和一串这样的数据:
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()运行。
随着extract从tidyr。extract将每个正则表达式捕获组变成它自己的列。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)
使用其他一些tidyverse工具,您可以通过unnesting list-column 并使用group_byandsummarise语义(更多dplyr方式)来解决这个问题,或者您可以按原样处理 list-col 并用于map_dbl从每一行中提取最大值和最小值(更多的purrr方式)。我的基准测试map_dbl比unnest和快约 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 日创建。