R tidytext Удалить слово, если оно входит в состав соответствующих биграмм, но сохранить, если нет - PullRequest
1 голос
/ 17 марта 2020

Используя unnest_token, я хочу создать текстовую подсказку, которая объединяет два разных токена: отдельные слова и биграммы. Причина заключается в том, что иногда отдельные слова являются более разумной единицей для изучения, а иногда это n-граммы более высокого порядка.

Если два слова отображаются как «разумный» биграмм, я хочу сохранить Биграм, а не хранить отдельные слова. Если те же слова появляются в другом контексте (т.е. не как биграмма), то я хочу сохранить их как отдельные слова.

В глупом примере ниже "of" важная биграмма. Таким образом, я хочу удалить отдельные слова «of» и «the», если они действительно появляются в тексте как «of». Но если «of» и «the» появляются в других комбинациях, я бы хотел оставить их как отдельные слова.

library(janeaustenr)
library(data.table)
library(dplyr)
library(tidytext)
library(tidyr)


# make unigrams
tide <- unnest_tokens(austen_books() , output = word, input = text )
# make bigrams
tide2 <- unnest_tokens(austen_books(), output = bigrams, input = text, token = "ngrams", n = 2)

# keep only most frequent bigrams (in reality use more sensible metric)
keepbigram <- names( sort( table(tide2$bigrams), decreasing = T)[1:10]  )
keepbigram
tide2 <- tide2[tide2$bigrams %in% keepbigram,]

# this removes all unigrams which show up in relevant bigrams
biwords <- unlist( strsplit( keepbigram, " ") )
biwords
tide[!(tide$word %in% biwords),]

# want to keep biwords in tide if they are not part of bigrams

1 Ответ

3 голосов
/ 17 марта 2020

Вы можете сделать это, заменив интересующие вас биграммы составным текстом в тексте перед токенизацией (т. Е. unnest_tokens):

keepbigram_new <- stringi::stri_replace_all_regex(keepbigram, "\\s+", "_")
keepbigram_new
#>  [1] "of_the"   "to_be"    "in_the"   "it_was"   "i_am"     "she_had" 
#>  [7] "of_her"   "to_the"   "she_was"  "had_been"

Использование _ вместо пробела является обычной практикой. за это. stringi::stri_replace_all_regex почти такой же, как gsub или str_replace из stringr, но немного быстрее и с большим количеством функций.

Теперь замените биграммы в тексте этими новыми соединениями перед токенизацией. Я использую регулярные выражения границы слова (\\b) в начале и конце биграмм, чтобы случайно не захватить, например, " из m":

topwords <- austen_books() %>% 
  mutate(text = stringi::stri_replace_all_regex(text, paste0("\\b", keepbigram, "\\b"), keepbigram_new, vectorize_all = FALSE)) %>% 
  unnest_tokens(output = word, input = text) %>% 
  count(word, sort = TRUE) %>% 
  mutate(rank = seq_along(word))

Глядя на большинство общие слова, первый биграмм появляется теперь на 40-м ранге:

topwords %>% 
  slice(1:4, 39:41)
#> # A tibble: 7 x 3
#>   word       n  rank
#>   <chr>  <int> <int>
#> 1 and    22515     1
#> 2 to     20152     2
#> 3 the    20072     3
#> 4 of     16984     4
#> 5 they    2983    39
#> 6 of_the  2833    40
#> 7 from    2795    41
...