Как извлечь самый длинный матч? - PullRequest
0 голосов
/ 21 мая 2018

Рассмотрим этот простой пример

library(stringr)
library(dplyr)

dataframe <- data_frame(text = c('how is the biggest ??',
                                 'really amazing stuff'))

# A tibble: 2 x 1
  text                 
  <chr>                
1 how is the biggest ??
2 really amazing stuff 

Мне нужно извлечь некоторые термины на основе выражения regex, , но извлечь только самый длинный термин .

До сих пор я мог извлечь только первый матч (не обязательно самый длинный), используя str_extract.

> dataframe %>% mutate(mymatch = str_extract(text, regex('\\w+')))
# A tibble: 2 x 2
  text                  mymatch
  <chr>                 <chr>  
1 how is the biggest ?? how    
2 really amazing stuff  really 

Я пытался играть с str_extract_all, но не могу найтиэффективный синтаксис.Вывод должен быть:

# A tibble: 2 x 2
  text                  mymatch
  <chr>                 <chr>  
1 how is the biggest ?? biggest
2 really amazing stuff  amazing 

Есть идеи?Спасибо!

Ответы [ 4 ]

0 голосов
/ 21 мая 2018

В качестве варианта других ответов я бы предложил написать функцию, которая выполняет манипуляцию

longest_match <- function(x, pattern) {
    matches <- str_match_all(x, pattern)
    purrr::map_chr(matches, ~ .[which.max(nchar(.))])
}

, а затем использовать ее

dataframe %>%
    mutate(mymatch = longest_match(text, "\\w+"))

В качестве комментария это кажется лучшепопрактиковаться, чтобы изолировать функцию, которая делает новый материал longest_match() от манипуляций, включенных mutate().Например, функция проста в тестировании, может использоваться в других обстоятельствах и может быть изменена («вернуть последнее, а не первое самое длинное совпадение») независимо от шага преобразования данных. Нет никакого реального смысла вставлять все в одинline, поэтому имеет смысл написать строки кода, которые логически выполняют одну вещь - найти все совпадения, отобразить все совпадения на самые длинные, ... purrr::map_chr() лучше, чем sapply(), потому что он более устойчив - он гарантируетчто результатом является символьный вектор, так что что-то вроде

> df1 = dataframe[FALSE,]
> df1 %>% mutate(mymatch = longest_match(text, "\\w+"))
# A tibble: 0 x 2
# ... with 2 variables: text <chr>, mymatch <chr>

«делает правильные вещи», т. е. mymatch является символьным вектором (sapply() вернет список в этом случае).

0 голосов
/ 21 мая 2018

Самый простой способ - разбить процесс на 2 шага, сначала список всех слов в каждой строке.Затем найдите и верните самое длинное слово из каждого подсписка:

df <- data_frame(text = c('how is the biggest ??',
                                 'really amazing stuff'))

library(stringr)
#create a list of all words per row
splits<-str_extract_all(df$text, '\\w+', simplify = FALSE)
#find longest word and return it
sapply(splits, function(x) {x[which.max(nchar(x))]})
0 голосов
/ 21 мая 2018

Или, используя purrr ...

library(dplyr)
library(purrr)
library(stringr)

dataframe %>% mutate(mymatch=map_chr(str_extract_all(text,"\\w+"),
                                     ~.[which.max(nchar(.))]))

# A tibble: 2 x 2
  text                  mymatch
  <chr>                 <chr>  
1 how is the biggest ?? biggest
2 really amazing stuff  amazing
0 голосов
/ 21 мая 2018

Вы можете сделать что-то вроде этого:

library(stringr)
library(dplyr)

dataframe %>%
  mutate(mymatch = sapply(str_extract_all(text, '\\w+'), 
                          function(x) x[nchar(x) == max(nchar(x))][1]))

С purrr:

library(purrr)

dataframe %>%
  mutate(mymatch = map_chr(str_extract_all(text, '\\w+'), 
                           ~ .[nchar(.) == max(nchar(.))][1]))

Результат:

# A tibble: 2 x 2
                   text mymatch
                  <chr>   <chr>
1 how is the biggest ?? biggest
2  really amazing stuff amazing

Примечание:

Если есть связь, то берется первая.

Данные:

dataframe <- data_frame(text = c('how is the biggest ??',
                                 'really amazing biggest stuff'))
...