Удаление нграмм, содержащих стоп-слова, используя тидитекст - PullRequest
2 голосов
/ 20 марта 2019

ОБНОВЛЕНИЕ: Спасибо за ваш вклад. Я переписал вопрос и добавил лучший пример, чтобы выделить неявные требования, которые не были рассмотрены в моем первом примере.

Вопрос Я ищу общее решение tidy для удаления нграмм, содержащих стоп-слова. Короче говоря, нграммы - это строки слов, разделенные пробелом. Униграмма содержит 1 слово, биграмма 2 слова и так далее. Моей целью было бы применить это к фрейму данных после использования unnest_tokens(). Решение должно работать с фреймом данных, содержащим смесь нграмм любой длины (uni, bi, tri ..) или, по крайней мере, bi & tri и выше.

Новый пример данных

ngram_df <- tibble::tribble(
  ~Document,                   ~ngram,
          1,                    "the",
          1,              "the basis",
          1,                  "basis",
          1,       "basis of culture",
          1,                "culture",
          1,        "is ground water",
          1,           "ground water",
          1, "ground water treatment"
  )
stopword_df <- tibble::tribble(
  ~word, ~lexicon,
  "the", "custom",
   "of", "custom",
   "is", "custom"
  )
desired_output <- tibble::tribble(
  ~Document,                   ~ngram,
          1,                  "basis",
          1,                "culture",
          1,           "ground water",
          1, "ground water treatment"
  )

Создано в 2019-03-21 с помощью пакета Представить (v0.2.1)

Желаемое поведение

  • ngram_df следует преобразовать в desired_output, используя стоп-слова из столбца word в stopword_df.
  • каждая строка, содержащая стоп-слово, должна быть удалена
  • следует соблюдать границы слов (то есть поиск is не должен удалять basis)


моя первая попытка репер ниже: пример данных library(tidyverse) library(tidytext) df <- "Groundwater remediation is the process that is used to treat polluted groundwater by removing the pollutants or converting them into harmless products." %>% enframe() %>% unnest_tokens(ngrams, value, "ngrams", n = 2) #apply magic here df #> # A tibble: 21 x 2 #> name ngrams #> <int> <chr> #> 1 1 groundwater remediation #> 2 1 remediation is #> 3 1 is the #> 4 1 the process #> 5 1 process that #> 6 1 that is #> 7 1 is used #> 8 1 used to #> 9 1 to treat #> 10 1 treat polluted #> # ... with 11 more rows пример списка стоп-слов stopwords <- c("is", "the", "that", "to") желаемый вывод #> Source: local data frame [9 x 2] #> Groups: <by row> #> #> # A tibble: 9 x 2 #> name ngrams #> <int> <chr> #> 1 1 groundwater remediation #> 2 1 treat polluted #> 3 1 polluted groundwater #> 4 1 groundwater by #> 5 1 by removing #> 6 1 pollutants or #> 7 1 or converting #> 8 1 them into #> 9 1 harmless products Создано в 2019-03-20 пакетом Представить (v0.2.1) (пример предложения из: https://en.wikipedia.org/wiki/Groundwater_remediation)

1 Ответ

0 голосов
/ 20 марта 2019

Здесь у вас есть другой способ, используя "stopwords_collapsed" из предыдущего ответа:

swc <- paste(stopwords, collapse = "|")
df <- df[str_detect(df$ngrams, swc) == FALSE, ] #select rows without stopwords

df
# A tibble: 8 x 2
   name ngrams                 
  <int> <chr>                  
1     1 groundwater remediation
2     1 treat polluted         
3     1 polluted groundwater   
4     1 groundwater by         
5     1 by removing            
6     1 pollutants or          
7     1 or converting          
8     1 harmless products 

Здесь у вас есть простой тест, сравнивающий обе системы:

#benchmark
txtexp <- rep(txt,1000000)
dfexp <- txtexp %>% 
    enframe() %>% 
    unnest_tokens(ngrams, value, "ngrams", n = 2)

benchmark("mutate+filter (small text)" = {df1 <- df %>%
        mutate(
            has_stop_word = str_detect(ngrams, stopwords_collapsed)
        ) %>%
        filter(!has_stop_word)},
          "[] row selection (small text)" = {df2 <- df[str_detect(df$ngrams, stopwords_collapsed) == FALSE, ]},
        "mutate+filter (large text)" = {df3 <- dfexp %>%
            mutate(
                has_stop_word = str_detect(ngrams, stopwords_collapsed)
            ) %>%
            filter(!has_stop_word)},
        "[] row selection (large text)" = {df4 <- dfexp[str_detect(dfexp$ngrams, stopwords_collapsed) == FALSE, ]},
          replications = 5,
          columns = c("test", "replications", "elapsed")
)

                           test replications elapsed
4 [] row selection (large text)            5   30.03
2 [] row selection (small text)            5    0.00
3    mutate+filter (large text)            5   30.64
1    mutate+filter (small text)            5    0.00
...