#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
). Двоичный поиск, конечно, медленный, но если мы сделаем некоторые предположения о замене (например, диапазон различий в количестве символов). Итак, вот основная идея:
- Превратите
Corpus
в уникальный набор слов, используяqdap
bag_o_words
- Найдите эти слова в словаре (
qdapDictionaries
‘DICTIONARY
набор данных), чтобы найти слова, которые не распознаются с помощьюmatch
- Это
misses
из шага # 2 будет то, что мы ищем
- Это
- Определите количество символов для слов в словаре, чтобы устранить грубую разницу позже, используя
nchar
- Запустите каждый элемент
misses
through a loop (sapply
) и выполните следующие действия:
a. запретите каждому элементуmisses
использоватьtm::stemDocument
б. определите количество символов и удалите из словаря те, которые не входят в этот диапазон, используяnchar
c. используйтеagrep
с помощью amax.distance
, чтобы исключить больше слов из словаря
d. используйте двоичный поиск (который перепроектируетagrep
), чтобы определить слово из словаря, которое ближе всего к пропущенному элементу [обратите внимание, что это не экспортируемая функция изqdap
calledqdap:::Ldist
] - Результатом является именованный вектор, который мы можем использовать для
gsub
bing tm_map
Используйте с пользовательской функцией для замены словtm
gsub
- Выполните обработку с помощью и
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
данных и позволяет вам затем применить «исправление» к любой новой текстовой строке (строкам).