Обработка с помощью анализа текста R

#r #text #tm #stemming

#r #текст #tm #обработка

Вопрос:

Я много анализирую TM пакет. Одна из моих самых больших проблем связана с основами и подобными им преобразованиями.

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

 accounts   -> account  
account    -> account  
accounting -> account  
acounting  -> acount  
acount     -> acount  
acounts    -> acount  
accounnt   -> accounnt  
 

Результат: 3 термина (учетная запись, учетная запись, учетная запись), где мне бы хотелось 1 (учетная запись), поскольку все они относятся к одному и тому же термину.

1) Исправить орфографию возможно, но я никогда не пытался сделать это в R. Возможно ли это вообще?

2) Другой вариант — создать список ссылок, т.е. account = (accounts, account, accounting, accounting, accounts, accountnt), а затем заменить все вхождения основным термином. Как бы я это сделал в R?

Еще раз, любая помощь / предложения будут с благодарностью приняты.

Ответ №1:

Мы могли бы создать список синонимов и заменить эти значения. Например

 synonyms <- list(
    list(word="account", syns=c("acount", "accounnt"))
)
 

Это говорит о том, что мы хотим заменить «acount» и «accountnt» на «account» (я предполагаю, что мы делаем это после завершения). Теперь давайте создадим тестовые данные.

 raw<-c("accounts", "account", "accounting", "acounting", 
     "acount", "acounts", "accounnt")
 

А теперь давайте определим функцию преобразования, которая заменит слова в нашем списке на основной синоним.

 library(tm)
replaceSynonyms <- content_transformer(function(x, syn=NULL) { 
    Reduce(function(a,b) {
        gsub(paste0("\b(", paste(b$syns, collapse="|"),")\b"), b$word, a)}, syn, x)   
})
 

Здесь мы используем content_transformer функцию для определения пользовательского преобразования. И в основном мы просто делаем a gsub , чтобы заменить каждое из слов. Затем мы можем использовать это в корпусе

 tm <- Corpus(VectorSource(raw))
tm <- tm_map(tm, stemDocument)
tm <- tm_map(tm, replaceSynonyms, synonyms)
inspect(tm)
 

и мы видим, что все эти значения преобразуются в «учетную запись» по желанию. Чтобы добавить другие синонимы, просто добавьте дополнительные списки в основной synonyms список. Каждый вложенный список должен иметь имена «word» и «syn».

Комментарии:

1. Отлично, это должно сработать для меня, но я должен скомпилировать списки вручную — это нормально. Гораздо больше контроля, чем раньше. Спасибо!

2. Только что протестировал это на своих живых данных — работает как шарм! Трудная часть состоит в том, чтобы прежде всего определить все варианты слов, а затем каким-то образом упростить / автоматизировать часть построения списка.

Ответ №2:

Мистер Флик ответил на вопрос № 2. Я подхожу к ответу на вопрос № 1.

Вот подход, в котором используется двоичный поиск по известной базе данных слов ( DICTIONARY из qdapDictionaries ). Двоичный поиск, конечно, медленный, но если мы сделаем некоторые предположения о замене (например, диапазон различий в количестве символов). Итак, вот основная идея:

  1. Превратите Corpus в уникальный набор слов, используя qdap bag_o_words
  2. Найдите эти слова в словаре ( qdapDictionaries DICTIONARY набор данных), чтобы найти слова, которые не распознаются с помощью match
    • Это misses из шага # 2 будет то, что мы ищем
  3. Определите количество символов для слов в словаре, чтобы устранить грубую разницу позже, используя nchar
  4. Запустите каждый элемент misses through a loop ( sapply ) и выполните следующие действия:
    a. запретите каждому элементу misses использовать tm::stemDocument
    б. определите количество символов и удалите из словаря те, которые не входят в этот диапазон, используя nchar
    c. используйте agrep с помощью a max.distance , чтобы исключить больше слов из словаря
    d. используйте двоичный поиск (который перепроектирует agrep ), чтобы определить слово из словаря, которое ближе всего к пропущенному элементу [обратите внимание, что это не экспортируемая функция из qdap called qdap:::Ldist ]
  5. Результатом является именованный вектор, который мы можем использовать для gsub bing
  6. tm_map Используйте с пользовательской функцией для замены слов tm gsub
  7. Выполните обработку с помощью и tm_map stemDocument

Вот код. Я сделал подделку Corpus , используя предоставленные вами слова и несколько случайных слов, чтобы продемонстрировать, как это сделать от начала до конца. Вы можете играть с range и max.distance это поставляется sapply . Чем слабее вы работаете с ними, тем медленнее будет поиск, но слишком сильное затягивание приведет к увеличению вероятности ошибки. Это действительно не ответ для исправления орфографии в общем смысле, но работает здесь, потому что вы все равно исходили. Есть Aspell пакет, но я никогда не использовал его раньше.

 terms <- c("accounts", "account", "accounting", "acounting", "acount", "acounts", "accounnt")

library(tm); library(qdap)

fake_text <- unlist(lapply(terms, function(x) {
    paste(sample(c(x, sample(DICTIONARY[[1]], sample(1:5, 1)))), collapse=" ")
}))

fake_text

myCorp <- Corpus(VectorSource(fake_text))
terms2 <- unique(bag_o_words(as.data.frame(myCorp)[[2]]))
misses <- terms2[is.na(match(terms2, DICTIONARY[[1]]))]

chars <- nchar(DICTIONARY[[1]])

replacements <- sapply(misses, function(x, range = 3, max.distance = .2) {
    x <- stemDocument(x)
    wchar <- nchar(x)
    dict <- DICTIONARY[[1]][chars >= (wchar - range) amp; chars <= (wchar   range)]
    dict <- dict[agrep(x, dict, max.distance=max.distance)]
    names(which.min(sapply(dict, qdap:::Ldist, x)))
})

replacer <- content_transformer(function(x) { 
    mgsub(names(replacements), replacements, x, ignore.case = FALSE, fixed = FALSE)
})

myCorp <- tm_map(myCorp, replacer)
inspect(myCorp <- tm_map(myCorp, stemDocument))
 

Комментарии:

1. Спасибо, Тайлер, на данный момент я думаю, что мне проще использовать решение MrFlick, поскольку у меня гораздо больше контроля над ним, НО вы подсказали мне несколько идей и пакетов для изучения, спасибо за ваше решение!

Ответ №3:

Этот вопрос вдохновил меня на попытку написать проверку орфографии для qdap пакета. Здесь может быть полезна интерактивная версия. Он доступен в qdap >= version 2.1.1 . Это означает, что на данный момент вам понадобится версия для разработчиков.. вот шаги по установке:

 library(devtools)
install_github("qdapDictionaries", "trinker")
install_github("qdap", "trinker")
library(tm); library(qdap)
 

## Воссоздайте Corpus то, что вы описываете.

 terms <- c("accounts", "account", "accounting", "acounting", "acount", "acounts", "accounnt")

fake_text <- unlist(lapply(terms, function(x) {
    paste(sample(c(x, sample(DICTIONARY[[1]], sample(1:5, 1)))), collapse=" ")
}))

fake_text

inspect(myCorp <- Corpus(VectorSource(fake_text)))
 

## Интерактивная проверка орфографии ( check_spelling_interactive )

 m <- check_spelling_interactive(as.data.frame(myCorp)[[2]])
preprocessed(m)
inspect(myCorp <- tm_map(myCorp, correct(m)))
 

correct Функция просто извлекает функцию закрытия из выходных check_spelling_interactive данных и позволяет вам затем применить «исправление» к любой новой текстовой строке (строкам).