Извлечение чисел из текста с помощью строки и регулярного выражения в R - PullRequest
0 голосов
/ 24 сентября 2018

У меня проблема с тем, что я пытаюсь извлечь числа из строки, содержащей текст и числа, а затем создать два новых столбца, показывающих минимальное и максимальное количество чисел.

Например, у меня есть один столбеци строка данных, подобная этой:

Text
Section 12345.01 to section 12345.02

И я хочу создать два новых столбца из данных в столбце Текст, например:

Min        Max   
12345.01   12345.02

Я использую dplyrи stringr с регулярным выражением, но регулярное выражение извлекает только первое вхождение шаблона (первое число).

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

Если я пытаюсь использовать функцию stringr::str_extract_all.Кажется, что он извлекает оба случая из шаблона, но он создает список в таблице, что, на мой взгляд, является настоящей проблемой.Так что я застрял на первом шаге, просто пытаясь вывести числа в свои столбцы.

Кто-нибудь может порекомендовать наиболее эффективный способ сделать это?В идеале я хотел бы извлечь числа из строки, преобразовать их в числа as.numeric и затем запустить функции min() и max().

Ответы [ 3 ]

0 голосов
/ 24 сентября 2018

Используя некоторые другие tidyverse инструменты, вы можете либо подойти к этому, unnest используя список-столбец и используя group_by и summarise семантику (более dplyr способ), либо вы можете просто иметь дело сlist-col как есть и используйте map_dbl для извлечения max и min из каждой строки (более purrr way).Мои тесты имеют map_dbl примерно в 7 раз быстрее, чем unnest и 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.

Создан в 2018-09-24 пакетом представлением (v0.2.0).

0 голосов
/ 24 сентября 2018

Уже были ответы, в которых говорится, как достичь вашей конечной цели, как это задано в вопросе, но просто для решения вопроса о том, как вы можете найти первое или второе совпадение с помощью пакета 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"

Создано в 2018-09-24 пакетом Представить (v0.2.0).

0 голосов
/ 24 сентября 2018

С 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))

Выход:

       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")
...