При работе с текстами, написанными на естественном языке, один из основных этапов — подготовка данных к анализу. В частности, уделение стоп-слов, приведение слов к одному регистру и так далее. Для таких задач я использую функции пакетов stringr и tm.

Один из первых шагов — это приведение текстов к одному регистру с помощью функции tolower():

txt <- "Мама мыла дегтярным мылом офицера Горчакова, пока его подчиненные курили в сенях"
tolower(txt)
#> [1] "мама мыла дегтярным мылом офицера горчакова, пока его подчиненные курили в сенях"

Следующий этап — это удаление стоп-слов. Наборы стоп-слов могут быть разными и зависеть от целей и задач исследования. Пакет tm также предлагает готовые наборы стоп-слов для разных языков, в том числе и русского. Посмотреть список для русского языка можно, выполнив команду stopwords("ru"). В нашем случае мы используем список стоп-слов, состоящий из частиц, предлогов и некоторых местоимений. Список взят из страниц Википедии, посвященных соответствующим частям речи и, естественно, не претендует на полноту:

library(tm)
stopwords <- c("в", "без", "до", "из", "к", "на", "по", "о", "от", "перед", "при", "через", "за", "над", "об", "под", "про", "для", "вблизи", "вглубь", "вдоль", "возле", "около", "вокруг", "впереди", "после", "посредством", "в роли", "в зависимости от", "путём", "насчёт", "по поводу", "ввиду", "по случаю", "в течение", "благодаря", "несмотря на", "спустя", "с ", "из-под", "из-за", "по-над", "в отличие от", "в связи", "как", "словно", "так как", "для того чтобы", "тоже", "зато", "чтобы", "также", "потому что", "и ", "а ", "что", "или", "но", "однако", "когда", "лишь", "едва", "где", "куда", "откуда", "столько", "настолько", "так", "до такой степени", "до того", "такой", "как будто", "будто", "точно", "как бы","если", "если бы", "коли", "ежели", "несмотря на то", "хотя", "хоть", "пускай", "дабы", "с тем чтобы", "так что", "ли", "не", "какой")
removeWords(txt, stopwords)
#> [1] "Мама мыла дегтярным мылом офицера Горчакова, пока его чиненные курили  сенях"

Как мы видим, функция removeWords() работает несколько некорректно: из слова «подчиненные» удаляет приставку «под», приняв ее за соответствующее стоп-слово. Такая ошибка характерна для текстов в не UTF8-кодировке и, вообще, нередко встречается у пользователей Windows. Так как проблема в кодировке, то самое простое решение — перекодировать весь массив записей. Проще всего в этих целях воспользоваться базовой функцией enc2utf8(). Аналогичная функция stri_enc_toutf8() из пакета stringi работает несколько медленнее (что незаметно при небольших датасетах, но критично при данных в десятки миллионов строк).

removeWords(enc2utf8(txt), stopwords)
#> [1] "Мама мыла дегтярным мылом офицера Горчакова, пока его подчиненные курили  сенях"

Аналогичным образом можно удалять знаки пунктуации. В пакете tm для этого предусмотрена функция removePunctuation(). И точно так же, как и при работе функции removeWords(), могут возникнуть сложности с некоторыми буквами, в частности, вместе с знаками препинания удаляется буква «ч»: «подиненные».

removePunctuation(enc2utf8(txt))
#> [1] "Мама мыла дегтярным мылом офицера Горчакова пока его подчиненные курили в сенях"

Последний штрих — удаление лишних пробелов, которые возникают после удаления стоп-слов, с помощью все той же базовой функции gsub(), а так же функции str_trim() из пакета stringr, которую мы используем для удалению пробелов в начале и в конце строки:

library(stringr)
txt <- removeWords(txt, stopwords)
txt <- gsub("\\s+", " ", txt)
txt <- str_trim(txt, side = "both")
print(txt)
#> [1] "Мама мыла дегтярным мылом офицера Горчакова, пока его подчиненные курили сенях"

Для упрощения работы все вышеперечисленные функции я предпочитаю вызывать в кастомной функции:

clean_text <- function(doc) {
    # подгружаем пакеты
    require(stringr)
    require(tm)
    # задаем список служебных слов
    stopwords <- c("в", "без", "до", "из", "к", "на", "по", "о", "от", "перед", "при", "через", "за", "над", "об", "под", "про", "для", "вблизи", "вглубь", "вдоль", "возле", "около", "вокруг", "впереди", "после", "посредством", "в роли", "в зависимости от", "путём", "насчёт", "по поводу", "ввиду", "по случаю", "в течение", "благодаря", "несмотря на", "спустя", "с ", "из-под", "из-за", "по-над", "в отличие от", "в связи", "как", "словно", "так как", "для того чтобы", "тоже", "зато", "чтобы", "также", "потому что", "и ", "а ", "что", "или", "но", "однако", "когда", "лишь", "едва", "где", "куда", "откуда", "столько", "настолько", "так", "до такой степени", "до того", "такой", "как будто", "будто", "точно", "как бы","если", "если бы", "коли", "ежели", "несмотря на то", "хотя", "хоть", "пускай", "дабы", "с тем чтобы", "так что", "ли", "не", "какой")
    doc <- tolower(doc)                               # приводим все к одному регистру
    doc <- enc2utf8(doc)                              # меняем кодировку
    doc <- removeWords(doc, stopwords)                # удаляем служебные слова, плохо работает с кириллицей в CP1251
    doc <- removePunctuation(doc)                     # удаляем знаки пунктуации, плохо работает с кириллицей в CP1251
    doc <- str_replace_all(doc, "\\s+", " ")          # удаляем лишние пробелы
    doc <- str_trim(doc, side = "both")               # удаляем пробелы в начале и в конце строки
    doc
}

clean_text(txt)
#> [1] "мама мыла дегтярным мылом офицера горчакова пока его подчиненные курили сенях"