diff --git a/book/1_introduction_to_r.qmd b/book/1_introduction_to_r.qmd index 10ea663..6a3af48 100644 --- a/book/1_introduction_to_r.qmd +++ b/book/1_introduction_to_r.qmd @@ -2,7 +2,7 @@ ## Установка R и RStudio -В данной книге используется исключительно R [@r_core_team], так что для занятий понадобятся: +В данном курсе используется исключительно R [@r_core_team], так что для занятий понадобятся: - R - [на Windows](https://cran.r-project.org/bin/windows/base/) @@ -14,7 +14,7 @@ sudo apt-get install r-base ``` - RStudio --- IDE для R ([можно скачать здесь](https://www.rstudio.com/products/rstudio/download/)) -* и некоторые пакеты на R +- и некоторые пакеты на R Часто можно увидеть или услышать, что R --- язык программирования для "статистической обработки данных". Изначально это, конечно, было правдой, но уже давно R --- это полноценный язык программирования, который при помощи своих пакетов позволяет решать огромный спектр задач. В данной книге используется следующая версия R: @@ -30,7 +30,7 @@ sessionInfo()$R.version$version.string |> cat() - [Jupyter](https://jupyter.org/) ноутбуки; - [Google Colab](https://colab.research.google.com) (нужно в настройках переключить ядро); - [VS Code](https://code.visualstudio.com/) --- другое IDE, которое также позволяет работать с R; -- в принципе, в IDE нет нужды, можно работать из терминала, после установки, нужно всего лишь набрать `R`. +- в принципе, в IDE нет нужды, можно работать из терминала, после установки нужно всего лишь набрать `R`. ## Знакомство с RStudio @@ -312,7 +312,7 @@ mean(c(1:50, NA), na.rm = TRUE) ## Датафреймы и их индексация -Датафрейм --- это один из основных объектов в R, в котором обычно импортируют и экспортируют табличные данные. Датафрейм --- это собрание векторов одинаковой длинны. Давайте создадим датафрейм: +Датафрейм --- это один из основных объектов в R, который обычно используется для импорта и экспорта табличных данные. Датафрейм --- это собрание векторов одинаковой длинны. Давайте создадим датафрейм: ```{r} df <- data.frame(name = c("Анна", "Вера", "Михаил"), @@ -363,7 +363,7 @@ iris ## Работа с пакетами -Все богатство R находиться в его огромной инфраструктуре пакетов, которые может разрабатывать кто-угодно: от больших компаний, до частных исследователей. Чтобы их установить, нужно использовать команду `install.packages()`. Начнем с установки центрального для курса пакета: `tidyverse`: +Все богатство R заключается в его огромной инфраструктуре пакетов, которые может разрабатывать кто угодно: от больших компаний до частных исследователей. Чтобы их установить, нужно использовать команду `install.packages()`. Начнем с установки центрального для курса пакета: `tidyverse`: ```{r} #| eval: false @@ -447,6 +447,6 @@ write_tsv(df, "orange_circumference_g100.tsv") write_delim(df, "orange_circumference_g100.zsv", delim = "0") ``` -## Как справятся с проблемами +## Как справляться с проблемами Код не работает очень часто, очень важно внимательно читать ошибки. Если чтение не помогло, то можно скопировать ошибку в поисковик, скорее всего кто-нибудь на Stack Overflow (место, где принято задавать вопрос) или Posit Community (место для вопросов на R и Python) уже сталкивался с вашей проблемой. Кроме того, никто не может написать пакет на R, который пройдет в основной репозиторий CRAN, не задокументировав все функции пакета. В связи с этим имеет смысл искать ответы во вкладке Help в Rstudio, а также в консоли, используя знак вопроса (или два, если ничего не находится) и имя функции, например, `?write_csv` или `??read_xlsx`. wd diff --git a/book/2_data_transformation.qmd b/book/2_data_transformation.qmd index 1da1b2a..18e33c1 100644 --- a/book/2_data_transformation.qmd +++ b/book/2_data_transformation.qmd @@ -49,7 +49,7 @@ c(1:100, NA) |> ## Функции семейства `slice()` -Дальше мы посмотрим на фрагмент данных из [исследования издания N+1](https://nplus1.ru/material/2019/06/19/greedy) дразнилки "Жадина-говядина", где исследовались социолингвистические аспекты влияющие на тенденцию к тому или иному продолжению. Переменные `word_1`, `word_2` и `word_3` соотвествуют разным вариантам начала, переменная `type` описывает классификацию, которую варианту дали исследователи, а переменная `n` отвечает за количество этих вариантов в данных. +Дальше мы посмотрим на фрагмент данных из ["Исследования дразнилки "Жадина-говядина" издания N+1](https://nplus1.ru/material/2019/06/19/greedy), где исследовались социолингвистические аспекты влияющие на тенденцию к тому или иному продолжению. Переменные `word_1`, `word_2` и `word_3` соотвествуют разным вариантам начала, переменная `type` описывает классификацию, которую варианту дали исследователи, а переменная `n` отвечает за количество этих вариантов в данных. ```{r} #| message: false @@ -57,7 +57,7 @@ zhadina <- read_csv("https://raw.githubusercontent.com/agricolamz/daR4hs/main/da zhadina ``` -Первые функции `tidyverse`, которая будет нас интересовать, --- это функции семейства `slice()`. Функция `slice()` позволяет фильтровать нужные строчки датасета по индексу: +Первые функции `tidyverse`, которые будут нас интересовать, --- это функции семейства `slice()`. Функция `slice()` позволяет фильтровать нужные строчки датасета по индексу: ```{r} zhadina |> @@ -67,7 +67,7 @@ zhadina |> slice(6:25) ``` -Стоит обратить внимание, что результат работы функции выводиться в консоль, чтобы сохранить результат работы, следует сделать операцию приписывания одним из следующих способов (первый наиболее распространенный): +Стоит обратить внимание, что результат работы функции выводится в консоль, чтобы сохранить результат работы, следует сделать операцию приписывания одним из следующих способов (первый наиболее распространенный): ```{r} new_zhadina <- zhadina |> @@ -145,7 +145,7 @@ zhadina |> ## Функция `filter()` -Функция `filter()` позволяет отфильтровыввать строки таблицы по одному или нескольким условиям. +Функция `filter()` позволяет отфильтровывать строки таблицы по одному или нескольким условиям. ```{r} zhadina |> @@ -176,7 +176,7 @@ zhadina |> filter(nchar(word_3) == 7) ``` -Кроме того, условия можно перечислить через запятую (аналог логического и): +Кроме того, условия можно перечислить через запятую (аналог логического "и"): ```{r} zhadina |> @@ -216,7 +216,7 @@ zhadina |> distinct(word_1, word_2) ``` -Функция `arrange()` позволяет отсортировать одну или несколько переменных от меньшего к большему (если нужно наоборот --- используйте функцию `desc()`). Числовые переменные соритруются по значения, а строковые по алфавиту (с учетом особенностей локали): +Функция `arrange()` позволяет отсортировать одну или несколько переменных от меньшего к большему (если нужно наоборот --- используйте функцию `desc()`). Числовые переменные сортируются по значениям, а строковые по алфавиту (с учетом особенностей локали, см. раздел @sec-sorting): ```{r} zhadina |> @@ -279,7 +279,7 @@ zhadina |> ## Функция `across()` -Функция `across()` позволяет применять одну и то же изменение к группе колонок, которые выбираются набором функций сходных с операциями для функции `select()`. Важно отметить, что трансформация обычно описывается функцией, и имя функции обычно пишут без круглых скобок. +Функция `across()` позволяет применять одно и то же изменение к группе колонок, которые выбираются набором функций сходных с операциями для функции `select()`. Важно отметить, что трансформация обычно описывается функцией, и имя функции обычно пишут без круглых скобок. ```{r} zhadina |> diff --git a/book/4_working_with_strings.qmd b/book/4_working_with_strings.qmd index e8aa9e2..fbf7ae4 100644 --- a/book/4_working_with_strings.qmd +++ b/book/4_working_with_strings.qmd @@ -22,7 +22,7 @@ library(tidyverse) library(stringi) ``` -Мы будем пользоваться в основном пакетами `stingr` и `stringi`, так как они в большинстве случаях удобнее. К счастью, функции этих пакетов легко отличить от остальных: функции пакет `stringr` всегда начинаются с `str_`, а функции пакета `stringi` --- c `stri_`. +Мы будем пользоваться в основном пакетами `stingr` и `stringi`, так как они в большинстве случаях удобнее. К счастью, функции этих пакетов легко отличить от остальных: функции пакета `stringr` всегда начинаются с `str_`, а функции пакета `stringi` --- c `stri_`. Существует [cheat sheet по `stringr`](https://github.com/rstudio/cheatsheets/raw/master/strings.pdf). @@ -126,7 +126,7 @@ tibble(month_name = month.name, mutate(long_string = str_glue("The {{month}} {month_name} is abbreviated as {month_abb}")) ``` -Для разделение строки на подстроки можно использовать функцию `separate()`. Это функция разносит разделенные элементы строки в соответствующие столбцы. У функции три обязательных аргумента: `col` --- колонка, которую следует разделить, `into` --- вектор названий новых столбец, `sep` --- разделитель. +Для разделения строки на подстроки можно использовать функцию `separate()`. Это функция разносит разделенные элементы строки в соответствующие столбцы. У функции три обязательных аргумента: `col` --- колонка, которую следует разделить, `into` --- вектор названий новых столбцов, `sep` --- разделитель. ```{r} tibble(upper = rev(LETTERS), smaller = letters) |> @@ -134,7 +134,7 @@ tibble(upper = rev(LETTERS), smaller = letters) |> separate(col = merge, into = c("column_1", "column_2"), sep = "_") ``` -Кроме того, есть инструмент `str_split()`, которая позволяет разбивать строки на подстроки, но возвращает *список*. +Кроме того, есть инструмент `str_split()`, который позволяет разбивать строки на подстроки, но возвращает *список*. ```{r} str_split(month.name, "r") @@ -195,7 +195,7 @@ tibble(mn = month.name) |> mutate(mn_new = str_pad(mn, 10, pad = ".")) ``` -## Сортировка +## Сортировка {#sec-sorting} Для сортировки существует `str_sort()`: @@ -208,7 +208,7 @@ str_sort(unsorted_cyrillic) str_sort(unsorted_cyrillic, locale = "ru_UA") ``` -Список локалей на копмьютере можно посмотреть командой `stringi::stri_locale_list()`. Список всех локалей вообще приведен [на этой странице](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes). Еще полезные команды: `stringi::stri_locale_info` и `stringi::stri_locale_set`. +Список локалей на компьютере можно посмотреть командой `stringi::stri_locale_list()`. Список всех локалей вообще приведен [на этой странице](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes). Еще полезные команды: `stringi::stri_locale_info` и `stringi::stri_locale_set`. ## Поиск подстроки Можно использовать функцию `str_detect()`: @@ -247,8 +247,8 @@ str_to_sentence(latin) ``` ### Выделение подстроки -Подстроку в строке можно выделить двумя способами: по индексам функцией `str_sub()`, и по подстроке функцией `str_png()`. +Подстроку в строке можно выделить двумя способами: по индексам функцией `str_sub()`, и по подстроке функцией `str_png()`. ```{r} tibble(mn = month.name) |> @@ -261,7 +261,7 @@ tibble(mn = month.name) |> mutate(mutate = str_extract(mn, "r")) ``` -По умолчанию функция `str_extract()` возвращает первое вхождение подстроки, соответствующей шаблону. Также существует функция `str_extract_all()`, которая возвращает все вхождения подстрок, соответствующих шаблону, однако возвращает объект типа список. +По умолчанию функция `str_extract()` возвращает первое вхождение подстроки, соответствующей шаблону. Также существует функция `str_extract_all()`, которая возвращает все вхождения подстрок, соответствующих шаблону в виде объекта типа список. ```{r} str_extract_all(month.name, "r") @@ -277,7 +277,7 @@ tibble(mn = month.name) |> mutate(mutate = str_replace(mn, "r", "R")) ``` -Как и другие функции `str_replace()` делает лишь одну замену, чтобы заменить все вхождения подстроки следует использовать функцию `str_replace_all()`: +Как и другие функции, `str_replace()` делает лишь одну замену, чтобы заменить все вхождения подстроки следует использовать функцию `str_replace_all()`: ```{r} @@ -287,7 +287,7 @@ tibble(mn = month.name) |> ### Удаление подстроки -Для удаления подстроки на основе шаблона, используется функция `str_remove()` и `str_remove_all()` +Для удаления подстроки на основе шаблона используется функция `str_remove()` и `str_remove_all()` ```{r} tibble(month.name) |> @@ -298,7 +298,7 @@ tibble(month.name) |> ### Транслитерация строк -В пакете `stringi` сууществует достаточно много методов транслитераций строк, которые можно вывести командой `stri_trans_list()`. Вот пример использования некоторых из них: +В пакете `stringi` существует достаточно много методов транслитераций строк, которые можно вывести командой `stri_trans_list()`. Вот пример использования некоторых из них: ```{r} stri_trans_general("stringi", "latin-cyrillic") @@ -314,7 +314,7 @@ stri_trans_general("stringi", "latin-armenian") - строка, с которой работает функция - образец (pattern) -Дальше мы будем использовать функцию `str_view()`, которая позволяет показывать, выделенное образцом в исходной строке. +Дальше мы будем использовать функцию `str_view()`, которая позволяет показывать выделенное образцом в исходной строке. ```{r} str_view("Я всегда путаю с и c", "c") # я ищу латинскую c diff --git a/book/5_working_with_texts.qmd b/book/5_working_with_texts.qmd index f494265..e1b6732 100644 --- a/book/5_working_with_texts.qmd +++ b/book/5_working_with_texts.qmd @@ -5,7 +5,7 @@ editor_options: --- # Работа с текстами -Не существует какого-то единого алгоритма анализа текстов, многое зависит от задач. Однако все обычные сферы анализа данных применимы к текстам: иногда нужно выделить какие-то составляющие текста (частота встречаемости каких-то единиц, сентимент анализ), иногда нужно выделить уникальные единицы свойственные какой-то группе текстов (мера tf-idf), иногда нужно кластеризовать тексты, чтобы найти похожие/разные тексты (например, класическая задача определения спамерских сообщений). Такие задачи находятся на стыке лингвистики и компьютерных наук. Существуют и более сложные/интеллектуальные задачи, которые традиционно относят к области исскуственного интеллекта, такие как перевод с одного языка на другой, саммаризация текста, вопросно-ответные системы и другие. В данном разделе мы коснемся лишь первой группы задач и пакеты, написанные на R для их решения. +Не существует какого-то единого алгоритма анализа текстов, многое зависит от задач. Однако все обычные сферы анализа данных применимы к текстам: иногда нужно выделить какие-то составляющие текста (частота встречаемости каких-то единиц, сентимент анализ), иногда нужно выделить уникальные единицы свойственные какой-то группе текстов (мера tf-idf), иногда нужно кластеризовать тексты, чтобы найти похожие/разные тексты (например, класическая задача определения спамерских сообщений). Такие задачи находятся на стыке лингвистики и компьютерных наук. Существуют и более сложные/интеллектуальные задачи, которые традиционно относят к области исскуственного интеллекта, такие как перевод с одного языка на другой, саммаризация текста, вопросно-ответные системы и другие. В данном разделе мы коснемся лишь первой группы задач и пакетов, написанных на R для их решения. ## Загрузка текстов в R {#sec-encoding} @@ -28,7 +28,7 @@ read_lines("https://raw.githubusercontent.com/agricolamz/daR4hs/main/data/w5_the n_max = 15) ``` -В функциях пакета `readr` (т. е. не только `read_lines()`, но и в функциях `read_csv()`, `read_tsv()` и т. п.) есть аргумент `locale`, который позволяет эксплицитно указать кодировку, а при считывании происходит процесс конвертации в стандартный для многих операционных систем `UTF-8`. Для текстов на русском языке важны следующие кодировки +В функциях пакета `readr` (т. е. не только в функции `read_lines()`, но и в функциях `read_csv()`, `read_tsv()` и т. п.) есть аргумент `locale`, который позволяет эксплицитно указать кодировку, а при считывании происходит процесс конвертации в стандартный для многих операционных систем `UTF-8`. Для текстов на русском языке важны следующие кодировки - `KOI8-R`, а для украинского языка --- `KOI8-U`; - `CP1251` (также известная под названием `Windows-1251`) покрывает и другие кириллические письменности такие как украинский, белорусский, болгарский, сербский, македонский и другие. @@ -78,7 +78,7 @@ x library(gutenbergr) ``` -Все самое важное в пакете хранится во встроенном датасете `gutenberg_metadata` --- аналоге: +Все самое важное в пакете хранится во встроенном датасете `gutenberg_metadata`: ```{r} str(gutenberg_metadata) @@ -126,7 +126,7 @@ books |> count(title) ``` -Обратите на аргумент `meta_fields`, который позволяет кроме самого текста добавить метаданные из `gutenberg_metadata` в получившийся датафрейм. +Обратите внимание на аргумент `meta_fields`, который позволяет кроме самого текста добавить метаданные из `gutenberg_metadata` в получившийся датафрейм. ### Пакет `rperseus` @@ -146,20 +146,20 @@ remotes::install_github("ropensci/rperseus") library(rperseus) ``` -Библиотечный каталог пакета `rperseus` находиться в переменной `perseus_catalog`: +Библиотечный каталог пакета `rperseus` находится в переменной `perseus_catalog`: ```{r} str(perseus_catalog) ``` -На каких языках содержаться тексты? +На каких языках содержатся тексты? ```{r} perseus_catalog |> count(language) ``` -А документации объясняется: +В документации объясняется: - `grc` --- греческий; - `lat` --- латинский; @@ -186,7 +186,7 @@ augustins_confession get_perseus_text("urn:cts:latinLit:stoa0040.stoa001.opp-lat1", excerpt = 4) ``` -К сожалению, пакет не позволяет скачивать много текстов за раз, но в документации описано как это можно сделать при помощи цикла. Кому-то может показаться полезной функция `perseus_parallel()`, которая позволяет видеть параллельные фрагменты текста. Проиллюстрируем это на примере Эвменид Эсхила: +К сожалению, пакет не позволяет скачивать много текстов за раз, но в документации описано, как это можно сделать при помощи цикла. Кому-то может показаться полезной функция `perseus_parallel()`, которая позволяет видеть параллельные фрагменты текста. Проиллюстрируем это на примере Эвменид Эсхила: ```{r eumenides} #| cache: true @@ -207,7 +207,7 @@ aeschylus_eumenides_eng |> ### Библиотека lib.ru -Для текстов на русском языке отдельного пакета не написали, однако на сайте библиотеки [lib.ru](lib.ru) они уже представлены в машиночитаемом виде, нужно всего лишь выбрать вариант отображение txt, полученную ссылку считать в R, указав корректную кодировку (см. @sec-encoding): +Для текстов на русском языке отдельного пакета не написали, однако на сайте библиотеки [lib.ru](lib.ru) они уже представлены в машиночитаемом виде, нужно всего лишь выбрать вариант отображения `txt`, полученную ссылку считать в R, указав корректную кодировку (см. @sec-encoding): ```{r} read_lines("http://lib.ru/LITRA/PUSHKIN/kapitan.txt_Ascii.txt", @@ -221,7 +221,6 @@ read_lines("http://lib.ru/LITRA/PUSHKIN/kapitan.txt_Ascii.txt", Сейчас скачанные тексты записывались в таблицу, где одна строка содержала один абзац. Однако для анализа текста нужно уметь работать с отдельными словами в нем. Для этого тексты нужно привести в tidy формат. С этим отлично справляется пакет `tidytext` (онлайн книга доступна [здесь](https://www.tidytextmining.com/)). Основное "оружие" пакета `tidytext` функция `unnest_tokens()`, которая переводит текст в tidy формат. В аргумент `output` подается вектор с именем будущей переменной, а аргумент `input` принимает переменную с текстом. - ```{r} library(tidytext) alices_adventures_in_wonderland |> @@ -229,7 +228,7 @@ alices_adventures_in_wonderland |> unnest_tokens(output = "word", input = text) ``` -По умолчанию функция `unnest_tokens()` удаляет знаки препинания и приводит слова к нижнему регистру. Давайте для удобства удалим все вплоть до оглавления и создадим датафрейм, в которых будет понятно, где какая глава книги: +По умолчанию функция `unnest_tokens()` удаляет знаки препинания и приводит слова к нижнему регистру. Давайте для удобства удалим все вплоть до оглавления и создадим датафрейм и переменную, из которой будет понятно, где какая глава книги: ```{r} alices_adventures_in_wonderland |> @@ -248,7 +247,7 @@ alices_adventures_in_wonderland |> alice_cleaned ``` -В приведенном выше коде интерес представляет функция `fill()`, которая заполнила пропущенные значения `NA` значениями выше. В остальном мы использовали не сложные регулярные выражения из @sec-regex. Кроме того мы воспользовались встроенными функциями `as.roman()` и `as.numeric()`, чтобы преобразовать римские номера глав в арабские. Теперь мы готовы анализировать частотность слов. Создадим переменную `tidy_alice` и посчитаем слова в каждой из глав: +В приведенном выше коде интерес представляет функция `fill()`, которая заполнила пропущенные значения `NA` значениями выше. В остальном мы использовали несложные регулярные выражения из @sec-regex. Кроме того, мы воспользовались встроенными функциями `as.roman()` и `as.numeric()`, чтобы преобразовать римские номера глав в арабские. Теперь мы готовы анализировать частотность слов. Создадим переменную `tidy_alice` и посчитаем слова в каждой из глав: ```{r} alice_cleaned |> @@ -272,7 +271,7 @@ tidy_alice |> labs(x = NULL, y = NULL) ``` -Хорошие знатоки "Алисы в Зазеркалье", конечно многое понимают из распределения местоимений *you* и, наверное, догадываются, почему это слово становиться первым, однако в большинстве случаев служебные слова неинформативны при анализе текстов. Для этого для некоторых языков составили списки стоп-слов --- служебных слов, которые никак не приближают к пониманию текста. Отдельный список уже встроен в пакет `tidytext` в переменную `stop_words` (см. также следующий раздел): +Хорошие знатоки "Алисы в Зазеркалье", конечно, многое понимают из распределения местоимений *you* и, наверное, догадываются, почему это слово становится первым, однако в большинстве случаев служебные слова неинформативны при анализе текстов. Поэтому для некоторых языков составили списки стоп-слов --- служебных слов, которые никак не приближают к пониманию текста. Отдельный список уже встроен в пакет `tidytext` в переменную `stop_words` (см. также следующий раздел): ```{r} stop_words @@ -292,7 +291,7 @@ tidy_alice |> labs(x = NULL, y = NULL) ``` -Получившийся результат уже значительно интереснее, однако алфавитный порядок слов в каждом фасете немного мешает. Для того, чтобы победить это в пакете `tidytext` есть нескольок функций: +Получившийся результат уже значительно интереснее, однако алфавитный порядок слов в каждом фасете немного мешает. Для того, чтобы победить это, в пакете `tidytext` есть несколько функций: - `reorder_within()` --- функция которая позволяет указать группировку, внутри которой нужно упорядочить единицы; - `scale_y_reordered()`/`scale_x_reordered()` --- функция, которая маскирует работу `reorder_within()` при отображении на графике. @@ -341,7 +340,7 @@ alice_cleaned |> ## Пакет `stopwords` -Выше мы упомянули, что в пакет `tidytext` встроен список английских стопслов. Стопслова для других язков можно раздобыть списки для других языков, используя пакет `stopwords`. Вместо имени языка, функция принимает ISO код языыка: +Выше мы упомянули, что в пакет `tidytext` встроен список английских стоп-слов. Стоп-слова для других язков можно раздобыть списки для других языков, используя пакет `stopwords`. Вместо имени языка, функция принимает ISO код языыка: ```{r} library(stopwords) @@ -369,7 +368,7 @@ length(stopwords("ru", source = "marimo")) length(stopwords("ru", source = "nltk")) ``` -В результате мы можем сделать анализ аналогичный анализу Алисы из прошлого раздела для русского текста: +В результате мы можем сделать анализ, аналогичный анализу Алисы из прошлого раздела, для текста на русском языке: ```{r} captains_daughter <- read_lines("https://raw.githubusercontent.com/agricolamz/daR4hs/main/data/w5_the_captains_daughter_koi8r.txt", @@ -419,7 +418,7 @@ udpipe("Жила-была на свете крыса в морском порт object = rumodel) ``` -После того как модель скачана можно к ней обращаться просто по имени файла: +После того, как модель скачана, можно к ней обращаться просто по имени файла: ```{r} udpipe("Жила-была на свете крыса в морском порту Вальпараисо, на складе мяса и маиса, какао и вина.", @@ -450,7 +449,7 @@ abstracts_dataset |> model ``` -Получившиеся эмбединги можно получить +Эмбединги из переменной `model` можно получить следующим образом: ```{r} as.matrix(model, which = "docs") |> @@ -470,4 +469,4 @@ as.matrix(model, which = "docs") |> stat_ellipse() ``` -Мы видим, что у аннотаций есть что-то общее, но в общем, аннотации распадаются на три группы. Важно, что расцветка у нас уже была в датасете и алгоритм векторизации ее не видел, так что получившееся пространство отражает карту анализируемых текстов. Стоит отметить, что качесвто получишвегося пространства напрямую зависит от объема данных. +Мы видим, что у аннотаций есть что-то общее, но, в общем, аннотации распадаются на три группы. Важно, что расцветка у нас уже была в датасете и алгоритм векторизации ее не видел, так что получившееся пространство отражает карту анализируемых текстов. Стоит отметить, что качество получившегося пространства напрямую зависит от объема данных. diff --git a/book/5_working_with_texts_files/figure-html/unnamed-chunk-39-1.png b/book/5_working_with_texts_files/figure-html/unnamed-chunk-39-1.png index 034c2ca..aa8b752 100644 Binary files a/book/5_working_with_texts_files/figure-html/unnamed-chunk-39-1.png and b/book/5_working_with_texts_files/figure-html/unnamed-chunk-39-1.png differ diff --git a/book/6_working_with_time.qmd b/book/6_working_with_time.qmd index 1a9054d..4bf3a62 100644 --- a/book/6_working_with_time.qmd +++ b/book/6_working_with_time.qmd @@ -53,7 +53,7 @@ today() now() ``` -Как видно, из этих функций в R можно работать как с датами, так и со временем. В качестве иллюстрации мы будем использовать датасет `flights` из пакета `nycflights13`, в котором содержатся данные полетов из Нью Йорка в 2013 года. +Как видно из этих функций в R можно работать как с датами, так и со временем. В качестве иллюстрации мы будем использовать датасет `flights` из пакета `nycflights13`, в котором содержатся данные полетов из Нью Йорка в 2013 году. ```{r} library(nycflights13) @@ -104,7 +104,7 @@ flights |> ## Работа с часовыми поясами -Земля разбита на условные географическо-административные зоны, в которых действуют свои правила работы со временем. В каких-то зонах есть переход на зимнее/летнее время, а где-то его нет. В некоторых точках Земли понятие часового пояса не имеет смысла, однако все равно есть конвенции того, какое время на этой теретории использовать. Функция `make_datetime()`, которую мы рассмотрели, использует по-умолчанию всемирное координированное время (UTC). Обозначение интересующего часового пояса можно посмотреть в интернете, однако основная информации о возможных значениях аргумента `tz` хранится в системе пользователя. +Земля разбита на условные географическо-административные зоны, в которых действуют свои правила работы со временем. В каких-то зонах есть переход на зимнее/летнее время, а где-то его нет. В некоторых точках Земли понятие часового пояса не имеет смысла, однако все равно есть конвенции того, какое время на этой территории использовать. Функция `make_datetime()`, которую мы рассмотрели, использует по-умолчанию всемирное координированное время (UTC). Обозначение интересующего часового пояса можно посмотреть в интернете, однако основная информации о возможных значениях аргумента `tz` хранится в системе пользователя. ```{r} dmy_hm("21-01-2001 15^43", tz = "Europe/Moscow") @@ -142,7 +142,7 @@ minute(date_example) second(date_example) ``` -Так же есть функция `leap_year()`, которая сообщает информацию, является ли выбранный год високосным: +Также есть функция `leap_year()`, которая сообщает, является ли выбранный год високосным: ```{r} leap_year(2019) @@ -159,11 +159,13 @@ ymd("2020-01-19") - ymd("2020-01-21") ``` Обратите внимание на результат работы этого выражения: + ```{r, message=FALSE} hm("21:00") - hm("18:10") ``` -Видимо, почему-то в таком использовании происходит поэлементная операция с часами, минутами, и секундами, так что в результате получаются отрицательные минуты. Однако, если использовать полные даты, то этого эффекта нет: +Видимо, почему-то при таком использовании происходит поэлементная операция с часами, минутами, и секундами, так что в результате получаются отрицательные минуты. Однако, если использовать полные даты, то этого эффекта нет: + ```{r} ymd_hm("2020-01-21, 21:00") - ymd_hm("2020-01-21, 18:10") ymd_hm("2020-01-21, 21:00") - hm("18:10") @@ -176,10 +178,10 @@ difftime(ymd_hm("2020-01-21, 21:00"), ymd_hm("2020-01-21, 18:10"), units = "mins difftime(ymd_hm("2020-01-21, 21:00"), ymd_hm("2020-01-21, 18:10"), units = "hours") ``` -Однако простые даты, не являются временными отрезками, так что их нельзя складывать, вычитать, умножать и т. д. Для удобства операций в `lubridate` вводится несколько сущностей: +Однако простые даты не являются временными отрезками, так что их нельзя складывать, вычитать, умножать и т. д. Для удобства операций в `lubridate` вводится несколько сущностей: -* **periods** --- промежутки времени, которые игнорируют нерегулярности во времени, сразу прибавляя 1 к соответствующему разряду, вводятся функциями `years()`, `months()`, `weeks()`, `days()`, `hours()`, `minutes()`, `seconds()`, `period()` -* **duration** --- промежутки времени, которые учитывают нерегулярности во времени, добавляя стандартную длительность единицы, вводятся функциями `dyears()`, `dweeks()`, `ddays()`, `dhours()`, `dminutes()`, `dseconds()`, `duration()` +- **periods** --- промежутки времени, которые игнорируют нерегулярности во времени, сразу прибавляя 1 к соответствующему разряду, вводятся функциями `years()`, `months()`, `weeks()`, `days()`, `hours()`, `minutes()`, `seconds()`, `period()` +- **duration** --- промежутки времени, которые учитывают нерегулярности во времени, добавляя стандартную длительность единицы, вводятся функциями `dyears()`, `dweeks()`, `ddays()`, `dhours()`, `dminutes()`, `dseconds()`, `duration()` ![](images/06_periods-durations.png) @@ -245,14 +247,15 @@ unwelcomed |> labs(y = "number of death/missing") ``` -Однако ко переменным со врменем не всегда относятся аккуратно. Рассмотрим график с сайта Левада-центра --- российской негосударственной исследовательской организации, которая проводит социологические и маркетинговые исследования (график взят [отсюда](https://www.levada.ru/indikatory/otnoshenie-k-stranam/)): +Однако к переменным со временем не всегда относятся аккуратно. Рассмотрим график с сайта Левада-центра --- российской негосударственной исследовательской организации, которая проводит социологические и маркетинговые исследования (график взят [отсюда](https://www.levada.ru/indikatory/otnoshenie-k-stranam/)): -![](images/11-levada.png) +![](images/06_levada.png) -На первый взгляд, в этом графике нет ничего странного, однако если присмотреться к динамической версии на сайте Левада-центра, можно обнаружить, что на идущие подряд измерения расположены на одинаковом расстоянии друг от друга, например, 05.2014, 07.2014, 11.2014. Вот [здесь](https://raw.githubusercontent.com/agricolamz/daR4hs/main/data/w6_2019.01_levada_countries.csv) можно скачать данные, по которым строился этот график. Вот как он выглядит, если считать временную переменную как время +На первый взгляд, в этом графике нет ничего странного, однако если присмотреться к динамической версии на сайте Левада-центра, можно обнаружить, что не идущие подряд значения расположены на одинаковом расстоянии друг от друга, например, 05.2014, 07.2014, 11.2014. Вот [здесь](https://raw.githubusercontent.com/agricolamz/daR4hs/main/data/w6_2019.01_levada_countries.csv) можно скачать данные, по которым строился этот график. Вот как он выглядит, если считать временную переменную как время ```{r, warning=FALSE,message=FALSE} levada <- read_csv("https://raw.githubusercontent.com/agricolamz/daR4hs/main/data/w6_2019.01_levada_countries.csv") + levada |> mutate(date = str_c("1-", date), date = dmy(date)) |> diff --git a/book/7_working_with_geodata.qmd b/book/7_working_with_geodata.qmd index 9b43e9a..1a87170 100644 --- a/book/7_working_with_geodata.qmd +++ b/book/7_working_with_geodata.qmd @@ -7,12 +7,12 @@ editor_options: ## Векторная и растровая графика -Перед тем как обсуждать карты, следует сначала обсудить разницу между векторной и растровой графикой. +Перед тем, как обсуждать карты, следует сначала обсудить разницу между векторной и растровой графикой. -- **Растровые изображения** представляют собой набор упорядоченных пикселей, про каждый из которых храниться информация о цвете. Векторное изображение нельзя бесконечно увеличивать --- в какой-то момент станут видны пиксели, которые в каком-то смысле являются пределом увелечения. Наиболее популярные форматы растровых изображений: `JPEG`, `GIF`, `PNG`, `BMP`, `TIFF` и другие. -- В **векторных изображениях** инормация храниться как собрани точек, линий и полигонов в некоторой системе координат, что позволяет бесконечно увеличивать такие изображения не теряя в качестве. Наиболее популярные форматы векторных изображений: `PDF`, `SVG`, `EPS` и другие. +- **Растровые изображения** представляют собой набор упорядоченных пикселей, про каждый из которых хранится информация о цвете. Векторное изображение нельзя бесконечно увеличивать --- в какой-то момент станут видны пиксели, которые в каком-то смысле являются пределом увеличения. Наиболее популярные форматы растровых изображений: `JPEG`, `GIF`, `PNG`, `BMP`, `TIFF` и другие. +- В **векторных изображениях** информация хранится как собрание точек, линий и полигонов в некоторой системе координат, что позволяет бесконечно увеличивать такие изображения не теряя в качестве. Наиболее популярные форматы векторных изображений: `PDF`, `SVG`, `EPS` и другие. -Современные технологии позволяют соединять растровые и векторные изображения, а также трансформировать их друг в друга. Картографические данные могут попадать в разные типы: точки (столицы всех стран), линии (улицы в каком-нибудь городе), полигоны (границы стран и меньших регионов) обычно имеют некоторую геопривязку (для простоты давайте считать такими, все, что имеет широту и долготу), так что могут быть представлены векторно, однако существует достаточно много информации, которую невозможно представить никак подругому, кроме как векторно: спутниковые снимки, существующие физические/политические/климатические/исторические и т. п. карты, выдача картографических сервисов, таких как Google Maps. Кроме того, занимаясь любыми типами визуализации следует помнить о разнице **статической визаулизации**, которую после создания нельзя изменить, и **динамической визуализации**, которая позволяет пользователям изменять себя (увеличиваться и уменьшаться, кликать на собрание точек и видеть их значения и т. п.). В данной главе, в отличие от предыдущих мы сосредоточимся на пакете для динамичского картографирования `leaflet`. Достаточно много тем останется за пределами этой главы: изменение проекции, манипуляции с географическими данными, работа с растровыми изображениями и другие (см., например, [@lovelace2019], доступная [он-лайн](https://geocompr.robinlovelace.net/)). +Современные технологии позволяют соединять растровые и векторные изображения, а также трансформировать их друг в друга. Картографические данные могут попадать в разные типы: точки (столицы всех стран), линии (улицы в каком-нибудь городе), полигоны (границы стран и меньших регионов) обычно имеют некоторую геопривязку (для простоты давайте считать таким все, что имеет широту и долготу), так что могут быть представлены векторно, однако существует достаточно много информации, которую невозможно представить никак по-другому, кроме как векторно: спутниковые снимки, существующие физические/политические/климатические/исторические и т. п. карты, выдача картографических сервисов, таких как Google Maps. Кроме того, занимаясь любыми типами визуализации следует помнить о разнице **статической визуализации**, которую после создания нельзя изменить, и **динамической визуализации**, которая позволяет пользователям изменять себя (увеличивать и уменьшать, кликать на собрание точек и видеть их значения и т. п.). В данной главе, в отличие от предыдущих, мы сосредоточимся на пакете для динамического картографирования `leaflet`. Достаточно много тем останется за пределами этой главы: изменение проекции, манипуляции с географическими данными, работа с растровыми изображениями и другие (см., например, [@lovelace2019], доступная [он-лайн](https://geocompr.robinlovelace.net/)). ## Картографические примитивы @@ -29,7 +29,7 @@ knitr::include_graphics("images/07_geographical_classes.png") ## Пакет leaflet -Мы пойдем необычным путем и начнем с инструмента, который создает динамические карты --- пакета `leaflet`, который является оберткой для одноименного популярного пакета для визаулизации карт в интернете на JS. +Мы пойдем необычным путем и начнем с инструмента, который создает динамические карты --- пакета `leaflet`, который является оберткой для одноименного популярного пакета для визуализации карт в интернете на JS. Для начала включим библиотеки: @@ -44,7 +44,7 @@ library("tidyverse") ### `.csv` файлы -Источником географических данных могут быть обычные привычные нам csv файлы. Например, вот [здесь](https://raw.githubusercontent.com/agricolamz/daR4hs/main/data/w6_death_of_migrants_and_refugees_from_the_Unwelcomed_project.csv), хранится датасет из проекта [The Unwelcomed](http://alhadaqa.com/2019/08/the_unwelcomed/) Мохамада А. Вэйкда (Mohamad A. Waked), содержащий информацию о месте и причинах смерти мигрантов и беженцев по всему миру с января 2014 года по июнь 2019 года. +Источником географических данных могут быть обычные привычные нам csv файлы. Например, вот [здесь](https://raw.githubusercontent.com/agricolamz/daR4hs/main/data/w6_death_of_migrants_and_refugees_from_the_Unwelcomed_project.csv) хранится датасет из проекта [The Unwelcomed](http://alhadaqa.com/2019/08/the_unwelcomed/) Мохамада А. Вэйкда (Mohamad A. Waked), содержащий информацию о месте и причинах смерти мигрантов и беженцев по всему миру с января 2014 года по июнь 2019 года. ```{r} #| message: false @@ -76,7 +76,7 @@ unwelcomed |> ### Формат `.geojson` -Существует несколько форматов, в которых принято распространять картографические данные, и если точки удобно хранить в `.csv` формате, то с полигонами и линиями `tidy` подход одно наблюдение -- одна строчка не подходит. Наиболее распространненые являюся `.geojson` и `.shp`. Формат `.geojson` можно прочитать при помощи функции `read_json()` из пакета `jsonlite` (я вызываю эту функцию, не загружая пакета, так как пакет `jsonlite` конфликтует с `tidyverse`): +Существует несколько форматов, в которых принято распространять картографические данные, и если точки удобно хранить в `.csv` формате, то с полигонами и линиями `tidy` подход одно наблюдение -- одна строчка не подходит. Наиболее распространенными являются `.geojson` и `.shp`. Формат `.geojson` можно прочитать при помощи функции `read_json()` из пакета `jsonlite` (я вызываю эту функцию, не загружая пакета, так как пакет `jsonlite` конфликтует с `tidyverse`): ```{r} moscow_districts <- jsonlite::read_json("https://raw.githubusercontent.com/agricolamz/daR4hs/main/data/w7_moscow.geojson") @@ -109,7 +109,7 @@ unwelcomed |> lat = ~lat) ``` -Функция `addCircles()` имеет массу аргументов, которая отвечает за отображение: +Функция `addCircles()` имеет массу аргументов, которые отвечают за отображение: * `radius` * `color` @@ -171,7 +171,7 @@ unwelcomed |> ### Комбинация карт: `leafsync` -Карты, как и все объекты в R тоже можно записать в переменную: +Карты, как и все объекты в R, тоже можно записать в переменную: ```{r} unwelcomed |> @@ -190,7 +190,7 @@ unwelcomed |> m_2014 ``` -Теперь если вызвать переменную `m_2014`, появится карта, которую мы сделали. Но, что если мы хотим отобразить рядом карты 2014 года и 2015 года? Как сделать фасетизацию? К сожалению, функции для фасетизации в пакете не предусмотрена, но мы можем сделать ее самостоятельно. Для начала создадим вторую карту: +Теперь, если вызвать переменную `m_2014`, появится карта, которую мы сделали. Но что, если мы хотим отобразить рядом карты 2014 года и 2015 года? Как сделать фасетизацию? К сожалению, функции для фасетизации в пакете не предусмотрено, но мы можем сделать ее самостоятельно. Для начала создадим вторую карту: ```{r} unwelcomed |> @@ -215,7 +215,7 @@ unwelcomed |> library(leafsync) ``` -И теперь соединим две карты воедино: +И теперь соединим две карты: ```{r} sync(m_2014, m_2015) diff --git a/book/index.qmd b/book/index.qmd index 42082e2..d8e4433 100644 --- a/book/index.qmd +++ b/book/index.qmd @@ -1,3 +1,3 @@ # Введение {.unnumbered} -Данные материалы являются конспектом онлайн курса Г. А. Мороз ‘Введение в анализ данных на R для гуманитарных и социальных наук’ \ No newline at end of file +Данные материалы являются конспектом онлайн курса Г. А. Мороза ‘Введение в анализ данных на R для гуманитарных и социальных наук’ \ No newline at end of file diff --git a/docs/1_introduction_to_r.html b/docs/1_introduction_to_r.html index fdf8c22..d5e6532 100644 --- a/docs/1_introduction_to_r.html +++ b/docs/1_introduction_to_r.html @@ -250,7 +250,7 @@

Table of contents

  • 1.9 Датафреймы и их индексация
  • 1.10 Работа с пакетами
  • 1.11 Чтение и запись табличных данных
  • -
  • 1.12 Как справятся с проблемами
  • +
  • 1.12 Как справляться с проблемами
  • @@ -278,7 +278,7 @@

    1 

    1.1 Установка R и RStudio

    -

    В данной книге используется исключительно R (R Core Team 2023), так что для занятий понадобятся:

    +

    В данном курсе используется исключительно R (R Core Team 2023), так что для занятий понадобятся: