Учебное пособие по библиотеке dplyr в R: объединение и соединение данных с примерами.
⚡ Умное резюме
Пакет dplyr объединяет и соединяет фреймы данных в R с помощью четырех методов: left_join(), right_join(), inner_join() и full_join(). Сопутствующий ему пакет tidyr затем преобразует результат объединения с помощью методов gather(), spread(), separate() и unite().

Введение в анализ данных
Перед любым присоединением или репостомping Использование глагола имеет смысл, это помогает понять, где уместна манипуляция данными. Анализ данных Его можно разделить на три части:
- Extracпроизводство: Во-первых, нам нужно собрать данные из многих источников и объединить их.
- Transform: Этот шаг включает в себя манипулирование данными. Как только мы объединим все источники данных, мы сможем приступить к очистке данных.
- Визуализируйте: Последний шаг — визуализировать наши данные, чтобы проверить их неравномерность.
На приведенной ниже диаграмме показано, как связаны между собой три этапа.

Одна из самых серьезных проблем, с которыми сталкиваются специалисты по анализу данных, — это обработка данных. Данные никогда не бывают доступны в желаемом формате. Специалистам по анализу данных необходимо тратить как минимум половину своего времени на очистку и обработку данных. Это одна из важнейших задач в их работе. Если процесс обработки данных не является полным, точным и тщательным, модель не будет работать корректно.
R dplyr
В R есть пакет dplyr, который занимается преобразованием данных. Он построен на основе небольшого набора основных функций — filter(), select(), arrange(), mutate() и summarise() — а также семейства функций объединения (join). После того, как данные будут сформированы, ggplot2 может их визуализировать.
Мы научимся использовать пакет dplyr для работы с файлами. Фрейм данныхЕсли R еще не установлен, следуйте инструкциям. Шаги по настройке R и RStudioЗатем выполните команду install.packages(“dplyr”).
Объединение данных с помощью dplyr
dplyr предоставляет приятный и удобный способ объединения наборов данных. У нас может быть много источников входных данных, и в какой-то момент нам потребуется их объединить. Соединение с dplyr добавляет переменные справа от исходного набора данных.
dplyr Joins
Ниже описаны четыре важных типа объединений, используемых в dplyr для слияния двух наборов данных. Все четыре принимают одни и те же аргументы — две таблицы и ключ — и отличаются только тем, какие несовпадающие строки остаются:
| Функция | Цель | аргументы | Несколько ключей |
|---|---|---|---|
| left_join() | Объедините два набора данных. Сохраняйте все наблюдения из исходной таблицы. | x, y, by = “ID” | x, y, by = c(“ID”, “ID2”) |
| right_join() | Объедините два набора данных. Сохраняйте все наблюдения из целевой таблицы. | x, y, by = “ID” | x, y, by = c(“ID”, “ID2”) |
| внутреннее соединение() | Объедините два набора данных. Исключите все строки, не соответствующие заданным параметрам. | x, y, by = “ID” | x, y, by = c(“ID”, “ID2”) |
| полное_соединение() | Объедините два набора данных. Сохраните все наблюдения. | x, y, by = “ID” | x, y, by = c(“ID”, “ID2”) |
Эти четыре глагола соответствуют левому, правому, внутреннему и полному внешнему соединениям SQLБазовый R достигает тех же результатов с помощью аргументов all, all.x и all.y. объединить ().
Мы рассмотрим все типы объединений на простом примере.
Прежде всего, мы создадим два набора данных. Таблица 1 содержит две переменные: ID и y, а Таблица 2 — ID и z. В каждом случае нам необходимо иметь пара ключей переменная. В нашем случае ID — это наш ключ переменная. Функция будет искать одинаковые значения в обеих таблицах и привязывать возвращаемые значения к правой части таблицы 1. На рисунке ниже показаны две таблицы рядом.
library(dplyr) df_primary <- tribble( ~ID, ~y, "A", 5, "B", 5, "C", 8, "D", 0, "F", 9) df_secondary <- tribble( ~ID, ~z, "A", 30, "B", 21, "C", 22, "D", 25, "E", 29)
dplyr left_join()
Наиболее распространенный способ объединения двух наборов данных — использование функции left_join(). На рисунке ниже показано, что пары ключ-соответствие соответствуют строкам A, B, C и D, а E и F остаются. С помощью left_join() мы сохраняем все строки из исходной таблицы и игнорируем строки, у которых нет пары ключ-соответствие в целевой таблице. В нашем примере значение E отсутствует в таблице 1, поэтому эта строка удаляется. Значение F берется из исходной таблицы, поэтому оно сохраняется после left_join() и возвращает NA в столбце z.
Пример dplyr left_join()
Приведённая ниже диаграмма воспроизводит то, что происходит во время выполнения функции left_join().
left_join(df_primary, df_secondary, by ='ID')
Выход:
## # A tibble: 5 x 3 ## ID y.x y.y ## <chr> <dbl> <dbl> ## 1 A 5 30 ## 2 B 5 21 ## 3 C 8 22 ## 4 D 0 25 ## 5 F 9 NA
Обратите внимание, что если обе таблицы содержат столбец с одинаковым именем, dplyr различает их с помощью суффиксов .x и .y, показанных выше.
dplyr right_join()
Функция right_join() работает точно так же, как left_join(). Единственная разница заключается в том, что строка удалена. Значение E, доступное в целевом фрейме данных, существует в новой таблице и принимает значение NA для столбца y.
Пример dplyr right_join()
На приведенной ниже диаграмме показано зеркальное изображение.
right_join(df_primary, df_secondary, by = 'ID')
Выход:
## # A tibble: 5 x 3 ## ID y.x y.y ## <chr> <dbl> <dbl> ## 1 A 5 30 ## 2 B 5 21 ## 3 C 8 22 ## 4 D 0 25 ## 5 E NA 29
dplyr inner_join()
Когда несовпадающие наблюдения оказываются совершенно бесполезными, мы можем вернуться Важно строки, которые существуют в и наборы данных. Это правильный выбор, когда нам нужен полный набор данных, и мы не хотим заполнять пропущенные значения средним или медианой.
Здесь на помощь приходит функция inner_join(). Она исключает несовпадающие строки с обеих сторон.
Пример dplyr Internal_join()
На приведенной ниже диаграмме выделены четыре идентификатора, которые сохраняются после объединения.
inner_join(df_primary, df_secondary, by ='ID')
Выход:
## # A tibble: 4 x 3 ## ID y.x y.y ## <chr> <dbl> <dbl> ## 1 A 5 30 ## 2 B 5 21 ## 3 C 8 22 ## 4 D 0 25
dplyr full_join()
Наконец, функция full_join() сохраняет все наблюдения и заменяет пропущенные значения на NA.
Пример dplyr full_join()
На приведенной ниже диаграмме показаны все идентификаторы из обеих таблиц, сохранившиеся после объединения.
full_join(df_primary, df_secondary, by = 'ID')
Выход:
## # A tibble: 6 x 3 ## ID y.x y.y ## <chr> <dbl> <dbl> ## 1 A 5 30 ## 2 B 5 21 ## 3 C 8 22 ## 4 D 0 25 ## 5 F 9 NA ## 6 E NA 29
Несколько пар ключей
И наконец, в нашем наборе данных может быть несколько ключей. Рассмотрим следующий набор данных, где у нас есть годы и список товаров, купленных клиентом. На скриншоте ниже показаны две таблицы и столбцы ID и год, которые вместе идентифицируют строку.
Если объединить обе таблицы только по ID, то каждый год будет сопоставлен с каждым годом, и количество строк резко возрастет. Чтобы исправить ситуацию, мы можем передать две переменные, представляющие собой пары ключ-год: ID и год, которые присутствуют в обоих наборах данных. Для объединения таблицы 1 и таблицы 2 можно использовать следующий код:
df_primary <- tribble( ~ID, ~year, ~items, "A", 2015,3, "A", 2016,7, "A", 2017,6, "B", 2015,4, "B", 2016,8, "B", 2017,7, "C", 2015,4, "C", 2016,6, "C", 2017,6) df_secondary <- tribble( ~ID, ~year, ~prices, "A", 2015,9, "A", 2016,8, "A", 2017,12, "B", 2015,13, "B", 2016,14, "B", 2017,6, "C", 2015,15, "C", 2016,15, "C", 2017,13) left_join(df_primary, df_secondary, by = c('ID', 'year'))
Выход:
## # A tibble: 9 x 4 ## ID year items prices ## <chr> <dbl> <dbl> <dbl> ## 1 A 2015 3 9 ## 2 A 2016 7 8 ## 3 A 2017 6 12 ## 4 B 2015 4 13 ## 5 B 2016 8 14 ## 6 B 2017 7 6 ## 7 C 2015 4 15 ## 8 C 2016 6 15 ## 9 C 2017 6 13
Начиная с версии dplyr 1.1.0 (январь 2023 г.) один и тот же ключ можно записать как join_by(ID, year), и dplyr теперь предупреждает о неожиданных совпадениях "многие ко многим", поскольку dplyr 1.1.0 присоединяется к анонсу .
Функции очистки данных в R
Объединение решает лишь половину проблемы, поскольку объединенную таблицу все равно необходимо переформатировать. Ниже приведены четыре важные функции для упорядочивания (очистки) данных:
| Функция | Цель | аргументы |
|---|---|---|
| собирать() | Преобразуйте данные из широких в длинные | (данные, ключ, значение, na.rm = ЛОЖЬ) |
| распространение() | Преобразование данных из длинных в широкие | (данные, ключ, значение) |
| отдельный() | Разделите одну переменную на две | (data, col, into, sep = “”, remove = TRUE) |
| объединить() | Объединить две переменные в одну. | (data, col, conc, sep = “”, remove = TRUE) |
Примечание к версии: Функции gather() и spread() были заменены на pivot_longer() и pivot_wider() в tidyr 1.0.0, а separate() — на семейство separate_wider_delim() в tidyr 1.3.0. Замененные функции по-прежнему работают, поэтому все приведенные ниже примеры работают, но в новом коде следует отдавать предпочтение более новым семействам функций, показанным в tidyr поворотная виньеткаФункция unite() остается актуальной.
Мы используем пакет tidyr, входящий в коллекцию tidyverse, для обработки, очистки и визуализации данных. Если R был установлен с Anaconda, этот пакет уже доступен по адресу [ссылка на пакет]. https://anaconda.org/r/r-tidyr.
Если он еще не установлен, введите следующую команду для установки tidyr:
install.packages("tidyr")
собирать()
Цель функции gather() — преобразовать данные из широкого формата в длинный.
Синтаксис
gather(data, key, value, na.rm = FALSE) Arguments: -data: The data frame used to reshape the dataset -key: Name of the new column created -value: Select the columns used to fill the key column -na.rm: Remove missing values. FALSE by default
Пример
Ниже мы можем наглядно представить концепцию решаping От широкой к длинной. Мы хотим создать один столбец с именем «рост», заполняемый строками переменных четверти. На рисунке ниже слева показана широкая таблица, а справа — измененная длинная таблица.
library(tidyr) # Create a messy dataset messy <- data.frame( country = c("A", "B", "C"), q1_2017 = c(0.03, 0.05, 0.01), q2_2017 = c(0.05, 0.07, 0.02), q3_2017 = c(0.04, 0.05, 0.01), q4_2017 = c(0.03, 0.02, 0.04)) messy
Выход:
## country q1_2017 q2_2017 q3_2017 q4_2017 ## 1 A 0.03 0.05 0.04 0.03 ## 2 B 0.05 0.07 0.05 0.02 ## 3 C 0.01 0.02 0.01 0.04
# Reshape the data
tidier <-messy %>%
gather(quarter, growth, q1_2017:q4_2017)
tidier
Выход:
## country quarter growth ## 1 A q1_2017 0.03 ## 2 B q1_2017 0.05 ## 3 C q1_2017 0.01 ## 4 A q2_2017 0.05 ## 5 B q2_2017 0.07 ## 6 C q2_2017 0.02 ## 7 A q3_2017 0.04 ## 8 B q3_2017 0.05 ## 9 C q3_2017 0.01 ## 10 A q4_2017 0.03 ## 11 B q4_2017 0.02 ## 12 C q4_2017 0.04
В функции gather() мы создаём две новые переменные, quarter и growth, поскольку наш исходный набор данных содержит одну групповую переменную country и пары ключ-значение. В tidyr 1.0.0 и более поздних версиях аналогичная операция преобразования записывается как pivot_longer(messy, cols = q1_2017:q4_2017, names_to = “quarter”, values_to = “growth”).
распространение()
Функция spread() делает противоположное тому, что делает функция gather().
Синтаксис
spread(data, key, value) arguments: data: The data frame used to reshape the dataset key: Column to reshape long to wide value: Rows used to fill the new column
Пример
Мы можем преобразовать более упорядоченный набор данных обратно в неупорядоченный с помощью функции spread().
# Reshape the data
messy_1 <- tidier %>%
spread(quarter, growth)
messy_1
Выход:
## country q1_2017 q2_2017 q3_2017 q4_2017 ## 1 A 0.03 0.05 0.04 0.03 ## 2 B 0.05 0.07 0.05 0.02 ## 3 C 0.01 0.02 0.01 0.04
Современный эквивалент — pivot_wider(tidier, names_from = quarter, values_from = growth).
отдельный()
Функция separate() разделяет столбец на две части в соответствии с разделителем. Эта функция полезна в ситуациях, когда переменная представляет собой дату. В нашем анализе может потребоваться сосредоточиться на месяце и годе, и мы хотим разделить столбец на две новые переменные.
Синтаксис
separate(data, col, into, sep= "", remove = TRUE) arguments: -data: The data frame used to reshape the dataset -col: The column to split -into: The name of the new variables -sep: Indicates the symbol used that separates the variable, i.e.: "-", "_", "&" -remove: Remove the old column. By default sets to TRUE.
Пример
Мы можем отделить квартал от года в более аккуратном наборе данных, применив функциюdependent().
separate_tidier <-tidier %>% separate(quarter, c("Qrt", "year"), sep ="_") head(separate_tidier)
Выход:
## country Qrt year growth ## 1 A q1 2017 0.03 ## 2 B q1 2017 0.05 ## 3 C q1 2017 0.01 ## 4 A q2 2017 0.05 ## 5 B q2 2017 0.07 ## 6 C q2 2017 0.02
объединить()
Функция unite() объединяет два столбца в один.
Синтаксис
unite(data, col, conc ,sep= "", remove = TRUE) arguments: -data: The data frame used to reshape the dataset -col: Name of the new column -conc: Name of the columns to concatenate -sep: Indicates the symbol used that unites the variable, i.e: "-", "_", "&" -remove: Remove the old columns. By default, sets to TRUE
Пример
В приведенном выше примере мы разделили квартал и год. А что, если мы хотим их объединить? Мы используем следующий код:
unit_tidier <- separate_tidier %>%
unite(Quarter, Qrt, year, sep ="_")
head(unit_tidier)
Выход:
## country Quarter growth ## 1 A q1_2017 0.03 ## 2 B q1_2017 0.05 ## 3 C q1_2017 0.01 ## 4 A q2_2017 0.05 ## 5 B q2_2017 0.07 ## 6 C q2_2017 0.02
Преобразованная структура данных теперь готова к этапам моделирования, описанным в остальной части статьи. Серия обучающих материалов по R.







