5 Работа со строками

5.1 Работа со строками в R

Для работы со строками можно использовать:

  • базовый R
  • пакет stringr (часть tidyverse)
  • пакет stringi – отдельный пакет, так что не забудьте его установить:
install.packages("stringi")
library(tidyverse)
library(stringi)

Мы будем пользоваться в основном пакетами stingr и stringi, так как они в большинстве случаях удобнее. К счастью функции этих пакетов легко отличить от остальных: функции пакет stringr всегда начинаются с str_, а функции пакета stringi — c stri_.

Существует cheat sheet по stringr.

5.2 Как получить строку?

  • следите за кавычками
"the quick brown fox jumps over the lazy dog"
## [1] "the quick brown fox jumps over the lazy dog"
'the quick brown fox jumps over the lazy dog'
## [1] "the quick brown fox jumps over the lazy dog"
"the quick 'brown' fox jumps over the lazy dog"
## [1] "the quick 'brown' fox jumps over the lazy dog"
'the quick "brown" fox jumps over the lazy dog'
## [1] "the quick \"brown\" fox jumps over the lazy dog"
  • пустая строка
""
## [1] ""
''
## [1] ""
character(3)
## [1] "" "" ""
  • преобразование
typeof(4:7)
## [1] "integer"
as.character(4:7)
## [1] "4" "5" "6" "7"
  • встроенные векторы
letters
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
LETTERS
##  [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
## [20] "T" "U" "V" "W" "X" "Y" "Z"
month.name
##  [1] "January"   "February"  "March"     "April"     "May"       "June"     
##  [7] "July"      "August"    "September" "October"   "November"  "December"
  • помните, что функции data.frame(), read.csv(), read.csv2(), read.table() из базового R всегда по-умолчанию преобразуют строки в факторы, и чтобы это предотвратить нужно использовать аргумент stringsAsFactors. Это много обсуждалось в сообществе R, можно, например, почитать про это вот этот блог пост Роджера Пенга.
str(data.frame(letters[6:10], LETTERS[4:8]))
## 'data.frame':	5 obs. of  2 variables:
##  $ letters.6.10.: chr  "f" "g" "h" "i" ...
##  $ LETTERS.4.8. : chr  "D" "E" "F" "G" ...
str(data.frame(letters[6:10], LETTERS[4:8], stringsAsFactors = FALSE))
## 'data.frame':	5 obs. of  2 variables:
##  $ letters.6.10.: chr  "f" "g" "h" "i" ...
##  $ LETTERS.4.8. : chr  "D" "E" "F" "G" ...

Но этом курсе мы учим использовать сразу tibble(), read_csv(), read_csv2(), read_tsv(), read_delim() из пакета readr (входит в tidyverse).

  • Создание рандомных строк
set.seed(42)
stri_rand_strings(n = 10, length = 5:14)
##  [1] "uwHpd"          "Wj8ehS"         "ivFSwy7"        "TYu8zw5V"      
##  [5] "OuRpjoOg0"      "p0CubNR2yQ"     "xtdycKLOm2k"    "fAGVfylZqBGp"  
##  [9] "gE28DTCi0NV0a"  "9MemYE55If0Cvv"
  • Перемешивает символы внутри строки
stri_rand_shuffle("любя, съешь щипцы, — вздохнёт мэр, — кайф жгуч")
## [1] ",цо м,пюзгу   сл аиъ—в кжряд,ыщьчебэн х—штё фй"
stri_rand_shuffle(month.name)
##  [1] "aJayunr"   "eyrbraFu"  "achMr"     "Aplri"     "ayM"       "Jnue"     
##  [7] "uJly"      "usuAgt"    "tpebermSe" "tOecrbo"   "oeNembvr"  "Dmceerbe"
  • Генерирует псевдорандомный текст1
stri_rand_lipsum(nparagraphs = 2)
## [1] "Lorem ipsum dolor sit amet, donec sit nunc urna sed ultricies ac pharetra orci luctus iaculis, ac tincidunt cum. Neque eu semper at sociosqu hendrerit. Eu aliquet lacus, eu hendrerit donec aliquam eros. Risus nibh, quam in sit facilisi ipsum. Amet sem sed donec sed molestie scelerisque tincidunt. Nisl donec et facilisis interdum non sed dolor purus. In ipsum dignissim torquent velit nec aliquam pellentesque. Ac, adipiscing, neque et at torquent, vestibulum ullamcorper. Ad dictumst enim velit non nulla felis habitant. Egestas placerat consectetur, dictum nostra sed nec. Erat phasellus dolor libero aliquam viverra. Vestibulum leo et. Suscipit egestas in in montes, sapien gravida? Conubia purus varius ut nec feugiat."
## [2] "Risus eleifend magnis neque diam, suspendisse ullamcorper nulla adipiscing malesuada massa, nisi sociosqu velit id et. Aliquam facilisis et aenean. Parturient vel ac in convallis, massa diam nibh. Nulla interdum cursus et. Natoque amet, ut praesent. Tortor ultrices a consectetur, augue natoque class faucibus? Ut sed arcu elementum magna. Dignissim ac facilisi quis ut nisl eu, massa."

5.3 Соединение и разделение строк

Соединенить строки можно используя функцию str_c(), в которую, как и в функции с(), можно перечислять элементы через запятую:

tibble(upper = rev(LETTERS), smaller = letters) %>% 
  mutate(merge = str_c(upper, smaller))

Кроме того, если хочется, можно использовать особенный разделитель, указав его в аргументе sep:

tibble(upper = rev(LETTERS), smaller = letters) %>% 
  mutate(merge = str_c(upper, smaller, sep = "_"))

Аналогичным образом, для разделение строки на подстроки можно использовать функцию separate(). Это функция разносит разделенные элементы строки в соответствующие столбцы. У функции три обязательных аргумента: col — колонка, которую следует разделить, into — вектор названий новых столбец, sep — разделитель.

tibble(upper = rev(LETTERS), smaller = letters) %>% 
  mutate(merge = str_c(upper, smaller, sep = "_")) %>% 
  separate(col = merge, into = c("column_1", "column_2"), sep = "_")

Кроме того, есть инструмент str_split(), которая позволяет разбивать строки на подстроки, но возвращает список.

str_split(month.name, "r")
## [[1]]
## [1] "Janua" "y"    
## 
## [[2]]
## [1] "Feb" "ua"  "y"  
## 
## [[3]]
## [1] "Ma" "ch"
## 
## [[4]]
## [1] "Ap" "il"
## 
## [[5]]
## [1] "May"
## 
## [[6]]
## [1] "June"
## 
## [[7]]
## [1] "July"
## 
## [[8]]
## [1] "August"
## 
## [[9]]
## [1] "Septembe" ""        
## 
## [[10]]
## [1] "Octobe" ""      
## 
## [[11]]
## [1] "Novembe" ""       
## 
## [[12]]
## [1] "Decembe" ""

5.4 Количество символов

5.4.1 Подсчет количества символов

tibble(mn = month.name) %>% 
  mutate(n_charactars = str_count(mn))

5.4.2 Подгонка количества символов

Можно обрезать строки, используя функцию str_trunc():

tibble(mn = month.name) %>% 
  mutate(mn_new = str_trunc(mn, 6))

Можно решить с какой стороны обрезать, используя аргумент side:

tibble(mn = month.name) %>% 
  mutate(mn_new = str_trunc(mn, 6, side = "left"))
tibble(mn = month.name) %>% 
  mutate(mn_new = str_trunc(mn, 6, side = "center"))

Можно заменить многоточие, используя аргумент ellipsis:

tibble(mn = month.name) %>% 
  mutate(mn_new = str_trunc(mn, 3, ellipsis = ""))

Можно наоборот “раздуть” строку:

tibble(mn = month.name) %>% 
  mutate(mn_new = str_pad(mn, 10))

Опять же есть аргумент side:

tibble(mn = month.name) %>% 
  mutate(mn_new = str_pad(mn, 10,  side = "right"))

Также можно выбрать, чем “раздувать строку”:

tibble(mn = month.name) %>% 
  mutate(mn_new = str_pad(mn, 10,  pad = "."))

На Pudding вышла статья про английские пабы. Здесь лежит немного обработанный датасет, которые они использовали. Визуализируйте 40 самых частотоных названий пабов в Великобритании, отложив по оси x количество символов, а по оси y – количество баров с таким названием.

📋 список подсказок ➡

👁 Датасет скачался, что дальше? ➡ Перво-наперво следует создать переменную, в которой бы хранилось количество каждого из баров.
👁 А как посчитать количество баров? ➡ Это можно сделать при помощи функции count().
👁 Бары пересчитали, что дальше? ➡ Теперь нужно создать новую переменную, где бы хранилась информация о количестве символов.
👁 Все переменные есть, теперь рисуем? ➡ Не совсем. Перед тем как рисовать нужно отфильтровать 50 самых популярных.
👁 Так, все готово, а какие geom_()? ➡ На графике geom_point() и geom_text_repel() из пакета ggrepel.
👁 А-а-а-а! could not find function "geom_text_repel" А вы включили библиотеку ggrepel? Если не включили, то функция, естественно будет недоступна.
👁 А-а-а-а! geom_text_repel requires the following missing aesthetics: label" Все, как написала программа: чтобы писать какой-то текст в функции aes() нужно добавить аргумент label = pub_name. Иначе откуда он узнает, что ему писать?
👁 Фуф! Все готово! ➡ А оси подписаны? А заголовок? А подпись про источник данных?

5.5 Сортировка

Для сортировки существует базовая функция sort() и функция из stringr str_sort():

unsorted_latin <- c("I", "♥", "N", "Y")
sort(unsorted_latin)
## [1] "♥" "I" "N" "Y"
str_sort(unsorted_latin)
## [1] "♥" "I" "N" "Y"
str_sort(unsorted_latin, locale = "lt")
## [1] "♥" "I" "Y" "N"
unsorted_cyrillic <- c("я", "i", "ж")
str_sort(unsorted_cyrillic)
## [1] "i" "ж" "я"
str_sort(unsorted_cyrillic, locale = "ru_UA")
## [1] "ж" "я" "i"

Список локалей на копмьютере можно посмотреть командой stringi::stri_locale_list(). Список всех локалей вообще приведен на этой странице. Еще полезные команды: stringi::stri_locale_info и stringi::stri_locale_set.

Не углубляясь в разнообразие алгоритмов сортировки, отмечу, что алгоритм по-умолчанию хуже работает с большими данными:

set.seed(42)
huge <- sample(letters, 1e7, replace = TRUE)
head(huge)
## [1] "q" "e" "a" "y" "j" "d"
system.time(
  sort(huge)
)
##    user  system elapsed 
##   7.359   0.024   7.383
system.time(
  sort(huge, method = "radix")
)
##    user  system elapsed 
##   0.330   0.028   0.358
system.time(
  str_sort(huge)
)
##    user  system elapsed 
##   6.566   0.072   6.679
huge_tbl <- tibble(huge)
system.time(
  huge_tbl %>% 
    arrange(huge)
)
##    user  system elapsed 
##   3.404   0.064   3.468

Предварительный вывод: для больших данных – sort(..., method = "radix").

5.6 Поиск подстроки

Можно использовать функцию str_detect():

tibble(mn = month.name) %>% 
  mutate(has_r = str_detect(mn, "r"))

Кроме того, существует функция, которая возвращает индексы, а не значения TRUE/FALSE:

tibble(mn = month.name) %>% 
  slice(str_which(month.name, "r"))

Также можно посчитать количество вхождений какой-то подстроки:

tibble(mn = month.name) %>% 
  mutate(has_r = str_count(mn, "r"))

5.7 Изменение строк

5.7.1 Изменение регистра

latin <- "tHe QuIcK BrOwN fOx JuMpS OvEr ThE lAzY dOg"
cyrillic <- "лЮбЯ, сЪеШь ЩиПцЫ, — вЗдОхНёТ мЭр, — кАйФ жГуЧ"
str_to_upper(latin)
## [1] "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG"
str_to_lower(cyrillic)
## [1] "любя, съешь щипцы, — вздохнёт мэр, — кайф жгуч"
str_to_title(latin)
## [1] "The Quick Brown Fox Jumps Over The Lazy Dog"

5.7.2 Выделение подстроки

Подстроку в строке можно выделить двумя способами: по индексам функцией str_sub(), и по подстроке функцией str_png().

extract(images/5.07_str_sub.png)

tibble(mn = month.name) %>% 
  mutate(mutate = str_sub(mn, start = 1, end = 2))

tibble(mn = month.name) %>% 
  mutate(mutate = str_extract(mn, "r"))

По умолчанию функция str_extract() возвращает первое вхождение подстроки, соответствующей шаблону. Также существует функция str_extract_all(), которая возвращает все вхождения подстрок, соответствующих шаблону, однако возвращает объект типа список.

str_extract_all(month.name, "r")
## [[1]]
## [1] "r"
## 
## [[2]]
## [1] "r" "r"
## 
## [[3]]
## [1] "r"
## 
## [[4]]
## [1] "r"
## 
## [[5]]
## character(0)
## 
## [[6]]
## character(0)
## 
## [[7]]
## character(0)
## 
## [[8]]
## character(0)
## 
## [[9]]
## [1] "r"
## 
## [[10]]
## [1] "r"
## 
## [[11]]
## [1] "r"
## 
## [[12]]
## [1] "r"

5.7.3 Замена подстроки

Существует функция str_replace(), которая позволяет заменить одну подстроку в строке на другую:

tibble(mn = month.name) %>% 
  mutate(mutate = str_replace(mn, "r", "R"))

Как и другие функции str_replace() делает лишь одну замену, чтобы заменить все вхождения подстроки следует использовать функцию str_replace_all():

tibble(mn = month.name) %>% 
  mutate(mutate = str_replace_all(mn, "r", "R"))

5.7.4 Удаление подстроки

Для удаления подстроки на основе шаблона, используется функция str_remove() и str_remove_all()

tibble(month.name) %>% 
  mutate(mutate = str_remove(month.name, "r"))
tibble(month.name) %>% 
  mutate(mutate = str_remove_all(month.name, "r"))

5.7.5 Транслитерация строк

В пакете stringi сууществует достаточно много методов транслитераций строк, которые можно вывести командой stri_trans_list(). Вот пример использования некоторых из них:

stri_trans_general("stringi", "latin-cyrillic")
## [1] "стринги"
stri_trans_general("сырники", "cyrillic-latin")
## [1] "syrniki"
stri_trans_general("stringi", "latin-greek")
## [1] "στριγγι"
stri_trans_general("stringi", "latin-armenian")
## [1] "ստրինգի"

Вот два датасета:

Определите сколько городов называется обычным словом русского языка (например, город Орёл)? Не забудьте поменять ё на е.

📋 список подсказок ➡

👁 Датасеты скачались, что дальше? ➡ Надо их преобразовать к нужному виду и объединить.
👁 А как их соединить? Что у них общего? ➡
В одном датасете есть переменная city, в другом – переменная lemma. Все города начинаются с большой буквы, все леммы с маленькой буквы. Я бы уменьшил букву в датасете с городами, сделал бы новый столбец в датасете с городами (например, town), соединил бы датасеты и посчитал бы сколько в результирующем датасете значений town.
👁 А как соеднить? ➡ Я бы использовал dict %>% ... %>% inner_join(cities). Если в датасетах разные названия столбцов, то следует указывать какие столбцы, каким соответствуют:dict %>% ... %>% inner_join(cities, by = c("lemma" = "city"))
👁 Соединилось вроде… А как посчитать? ➡ Я бы, как обычно, использовал функцию count().

5.8 Регулярные выражения

Большинство функций из раздела об операциях над векторами (str_detect(), str_extract(), str_remove() и т. п.) имеют следующую структуру:

  • строка, с которой работает функция
  • образец (pattern)

Дальше мы будем использовать функцию str_view_all(), которая позволяет показывать, выделенное образцом в исходной строке.

str_view_all("Я всегда путаю с и c", "c") # я ищу латинскую c

5.8.1 Экранирование метасимволов

a <- "Всем известно, что 4$\\2 + 3$ * 5 = 17$? Да? Ну хорошо (а то я не был уверен). [|}^{|]"
str_view_all(a, "$")
str_view_all(a, "\\$")
str_view_all(a, "\\.")
str_view_all(a, "\\*")
str_view_all(a, "\\+")
str_view_all(a, "\\?")
str_view_all(a, "\\(")
str_view_all(a, "\\)")
str_view_all(a, "\\|")
str_view_all(a, "\\^")
str_view_all(a, "\\[")
str_view_all(a, "\\]")
str_view_all(a, "\\{")
str_view_all(a, "\\}")
str_view_all(a, "\\\\")

5.8.2 Классы знаков

  • \\d – цифры. \\D – не цифры.
str_view_all("два 15 42. 42 15. 37 08 5. 20 20 20!", "\\d")
str_view_all("два 15 42. 42 15. 37 08 5. 20 20 20!", "\\D")
  • \\s – пробелы. \\S – не пробелы.
str_view_all("два 15 42. 42 15. 37 08 5. 20 20 20!", "\\s")
str_view_all("два 15 42. 42 15. 37 08 5. 20 20 20!", "\\S")
  • \\w – не пробелы и не знаки препинания. \\W – пробелы и знаки препинания.
str_view_all("два 15 42. 42 15. 37 08 5. 20 20 20!", "\\w")
str_view_all("два 15 42. 42 15. 37 08 5. 20 20 20!", "\\W")
  • произвольная группа символов и обратная к ней
str_view_all("Умей мечтать, не став рабом мечтанья", "[оауиыэёеяю]")
str_view_all("И мыслить, мысли не обожествив", "[^оауиыэёеяю]")
  • встроенные группы символов
str_view_all("два 15 42. 42 15. 37 08 5. 20 20 20!", "[0-9]")
str_view_all("Карл у Клары украл кораллы, а Клара у Карла украла кларнет", "[а-я]")
str_view_all("Карл у Клары украл кораллы, а Клара у Карла украла кларнет", "[А-Я]")
str_view_all("Карл у Клары украл кораллы, а Клара у Карла украла кларнет", "[А-я]")
str_view_all("The quick brown Fox jumps over the lazy Dog", "[a-z]")
str_view_all("два 15 42. 42 15. 37 08 5. 20 20 20!", "[^0-9]")

  • выбор из нескольких групп
str_view_all("Карл у Клары украл кораллы, а Клара у Карла украла кларнет", "лар|рал|арл")
  • произвольный символ
str_view_all("Везет Сенька Саньку с Сонькой на санках. Санки скок, Сеньку с ног, Соньку в лоб, все — в сугроб", "[Сс].н")
  • знак начала и конца строки
str_view_all("от топота копыт пыль по полю летит.", "^о")
str_view_all("У ежа — ежата, у ужа — ужата", "жата$")
  • есть еще другие группы и другие обозначения уже приведенных групп, см. ?regex

5.8.3 Квантификация

  • ? – ноль или один раз
str_view_all("хорошее длинношеее животное", "еее?")
  • * – ноль и более раз
str_view_all("хорошее длинношеее животное", "ее*")
  • + – один и более раз
str_view_all("хорошее длинношеее животное", "е+")
  • {n}n раз
str_view_all("хорошее длинношеее животное", "е{2}")
  • {n,}n раз и более
str_view_all("хорошее длинношеее животное", "е{1,}")
  • {n,m} – от n до m. Отсутствие пробела важно: {1,2} – правильно, {1,␣2} – неправильно.
str_view_all("хорошее длинношеее животное", "е{2,3}")
  • группировка символов
str_view_all("Пушкиновед, Лермонтовед, Лермонтововед", "(ов)+")
str_view_all("беловатый, розоватый, розововатый", "(ов)+")
  • жадный vs. нежадный алоритмы
str_view_all("Пушкиновед, Лермонтовед, Лермонтововед", "в.*ед")
str_view_all("Пушкиновед, Лермонтовед, Лермонтововед", "в.*?ед")

5.8.4 Позиционная проверка (look arounds)

Позиционная проверка – выглядит достаточно непоследовательно даже в свете остальных регулярных выражений.

Давайте найдем все а перед р:

str_view_all("Карл у Клары украл кораллы, а Клара у Карла украла кларнет", "а(?=р)")

А теперь все а перед р или л:

str_view_all("Карл у Клары украл кораллы, а Клара у Карла украла кларнет", "а(?=[рл])")

Давайте найдем все а после р

str_view_all("Карл у Клары украл кораллы, а Клара у Карла украла кларнет", "(?<=р)а")

А теперь все а после р или л:

str_view_all("Карл у Клары украл кораллы, а Клара у Карла украла кларнет", "(?<=[рл])а")

Также у этих выражений есть формы с отрицанием. Давайте найдем все р не перед а:

str_view_all("Карл у Клары украл кораллы, а Клара у Карла украла кларнет", "р(?!а)")

А теперь все р не после а:

str_view_all("Карл у Клары украл кораллы, а Клара у Карла украла кларнет", "(?<!а)р")

Запомнить с ходу это достаточно сложно, так что подсматривайте сюда:

Вот отсюда можно скачать файл с текстом стихотворения Н. Заболоцкого “Меркнут знаки задиака”. Посчитайте долю женских (ударение падает на предпоследний слог рифмующихся слов) и мужских (ударение падает на последний слог рифмующихся слов) рифм в стихотворении.

📋 список подсказок ➡

👁 Датасеты скачивается с ошибкой, почему? ➡ Дело в том, что исходный файл в формате .txt, а не .csv. Его нужно скачивать, например, командой read_lines()
👁 Ошибка: ...applied to an object of class "character"
Скачав файл Вы получили вектор со строками, где каждая элимент вектора – строка стихотворения. Создайте tibble(), тогда можно будет применять стандартные инструменты tidyverse.
👁 Хорошо, tibble() создан, что дальше? ➡ Дальше нужно создать переменную, из которой будет понятно, мужская в каждой строке рифма, или женская.
👁 А как определить, какая рифма? Нужно с словарем сравнивать? ➡ Формально говоря, определять рифму можно по косвенным признакам. Все стихотворение написано четырехстопным хореем, значит в нем либо 7, либо 8 слогов. Значит, посчитав количество слогов, мы поймем, какая перед нами рифма.
👁 А как посчитать гласные? ➡ Нужно написать регулярное выражение… вроде бы это тема нашего занятия…
👁 Гласные посчитаны. А что дальше? ➡ Ну теперь нужно посчитать, сколько каких длин (в количестве слогов) бывает в стихотворении. Это можно сделать при помощи функции count().
👁 А почему у меня есть строки длины 0 слогов ➡ Ну, видимо, в стихотворении были пустые строки. Они использовались для разделения строф.
👁 А почему у меня есть строки длины 6 слогов ➡ Ну, видимо, Вы написали регулярное выражение, которое не учитывает, что гласные буквы могут быть еще и в начале строки, а значит написаны с большой буквы.

В ходе анализа данных чаще всего бороться со строками и регулярными выражениями приходится в процессе обработки неаккуратнособранных анкет. Предлагаю обработать переменные sex и age такой вот неудачно собранной анкеты и построить следующий график:

📋 список подсказок ➡

👁 А что это за geom_...()? ➡ Это geom_dotplot() с аргументом method = "histodot" и с удаленной осью y при помощи команды scale_y_continuous(NULL, breaks = NULL)
👁 Почему на графике рисутеся каждое значение возраста? ➡ Если Вы все правильно преобразовали, должно помочь преобразование строковой переменной age в числовую при помощи функции as.integer().

5.9 Определение языка

Для определения языка существует два пакета cld2 (вероятностный) и cld3 (нейросеть).

udhr_24 <- read_csv("https://raw.githubusercontent.com/agricolamz/DS_for_DH/master/data/article_24_from_UDHR.csv")
## Parsed with column specification:
## cols(
##   article_text = col_character()
## )
udhr_24
cld2::detect_language(udhr_24$article_text)
## [1] "ru" "en" "fr" "es" "ar" "zh"
cld2::detect_language(udhr_24$article_text, lang_code = FALSE)
## [1] "RUSSIAN" "ENGLISH" "FRENCH"  "SPANISH" "ARABIC"  "CHINESE"
cld3::detect_language(udhr_24$article_text)
## [1] "ru" "en" "fr" "es" "ar" "zh"
cld2::detect_language("Ты женат? Говорите ли по-английски?")
## [1] "bg"
cld3::detect_language("Ты женат? Говорите ли по-английски?")
## [1] NA
cld2::detect_language("Варкалось. Хливкие шорьки пырялись по наве, и хрюкотали зелюки, как мюмзики в мове.")
## [1] "ru"
cld3::detect_language("Варкалось. Хливкие шорьки пырялись по наве, и хрюкотали зелюки, как мюмзики в мове.")
## [1] "ru"
cld2::detect_language("Варчилось… Хлив'язкі тхурки викрули, свербчись навкрузі, жасумновілі худоки гривіли зехряки в чузі.")
## [1] "uk"
cld3::detect_language("Варчилось… Хлив'язкі тхурки викрули, свербчись навкрузі, жасумновілі худоки гривіли зехряки в чузі.")
## [1] "uk"
cld2::detect_language_mixed("Многие в нашей команде OpenDataScience занимаются state-of-the-art технологиями машинного обучения: DL-фреймворками, байесовскими методами машинного обучения, вероятностным программированием и не только.")
## $classificaton
##   language code latin proportion
## 1  RUSSIAN   ru FALSE       0.87
## 2  ENGLISH   en  TRUE       0.11
## 3  UNKNOWN   un  TRUE       0.00
## 
## $bytes
## [1] 353
## 
## $reliabale
## [1] TRUE
cld3::detect_language_mixed("Многие в нашей команде OpenDataScience занимаются state-of-the-art технологиями машинного обучения: DL-фреймворками, байесовскими методами машинного обучения, вероятностным программированием и не только.")

5.10 Расстояния между строками

Существует много разных метрик для измерения расстояния между строками (см. ?`stringdist-metrics`), в примерах используется расстояние Дамерау — Левенштейна. Данное расстояние получается при подсчете количества операций, которые нужно сделать, чтобы перевести одну строку в другую.

  • вставка ab → aNb
  • удаление aOb → ab
  • замена символа aOb → aNb
  • перестановка символов ab → ba
library(stringdist)
## 
## Attaching package: 'stringdist'
## The following object is masked from 'package:tidyr':
## 
##     extract
stringdist("корова","корова")
## [1] 0
stringdist("коровы", c("курица", "бык", "утка", "корова", "осел"))
## [1] 4 6 6 1 5
amatch(c("быки", "коровы"), c("курица", "бык", "утка", "корова", "осел"), maxDist = 2)
## [1] 2 4

  1. Lorem ipsum — классический текст-заполнитель на основе трактата Марка Туллия Цицерона “О пределах добра и зла”. Его используют, чтобы посмотреть, как страница смотриться, когда заполнена текстом↩︎