Злиття кадрів даних у R: повна та часткова відповідність
⚡ Розумний підсумок
Об'єднання фреймів даних у R об'єднує дві таблиці за одним або кількома стовпцями зі спільним ключем. Функція merge() охоплює внутрішнє, ліве, праве та повне об'єднання, і в цьому покроковому посібнику демонструється як повне, так і часткове збіг.
Дуже часто ми маємо дані з кількох джерел. Щоб провести аналіз, нам потрібно злиття два кадри даних разом з одним або кількома загальні ключові змінні.
Типи злиття (Join) в R
Перш ніж розглядати приклади, варто знати, що merge() виконує кожен тип об'єднання, який очікує користувач SQL. Поведінка контролюється аргументами all, all.x та all.y, а не іншим ім'ям функції.
| Тип приєднання | Рядки збережено | виклик merge() | еквівалент dplyr |
|---|---|---|---|
| Внутрішнє з'єднання (за замовчуванням) | Тільки ключі присутні в обох кадрах | злиття(x, y, при = “k”) | inner_join(x, y, by = “k”) |
| Ліве зовнішнє з'єднання | Усі рядки x, NA, де y не має збігів | злиття(x, y, by = “k”, all.x = TRUE) | ліворуч_з'єднання(x, y, при = “k”) |
| Правий зовнішній з’єднання | Усі рядки y, NA, де x не має збігів | злиття(x, y, by = “k”, all.y = TRUE) | right_join(x, y, by = “k”) |
| Повне зовнішнє з'єднання | Кожен рядок з обох рамок | злиття(x, y, при = “k”, усі = TRUE) | повне_з'єднання(x, y, при = “k”) |
| Хрест з'єднати | Кожна комбінація рядків | злиття(x, y, за = NULL) | перехресне_з'єднання(x, y) |
Перед першим дзвінком варто пам'ятати про дві деталі:
- Якщо не вказати "by", R об'єднує всі назви стовпців, які спільно використовують два фрейми, що рідко буває потрібним.
- merge() сортує результат за ключовим стовпцем; передайте sort = FALSE, щоб зберегти порядок вхідних значень.
Повний матч
Повний збіг повертає лише значення, які мають аналог у цільовій таблиці. Рядки без збігу видаляються з нового фрейму даних. Частковий збіг, навпаки, зберігає ці рядки та заповнює відсутні стовпці значенням NA.
Ми побачимо простий inner join. Ключове слово inner join вибирає записи, які мають відповідні значення в обох таблицях. Щоб об’єднати два набори даних, ми можемо використати функцію merge(). Ми будемо використовувати три аргументи:
merge(x, y, by.x = x, by.y = y) Arguments: -x: The origin data frame -y: The data frame to merge -by.x: The column used for merging in x data frame. Column x to merge on -by.y: The column used for merging in y data frame. Column y to merge on
приклад:
Створіть перший набір даних зі змінними
- прізвище
- громадянство
Створіть другий набір даних зі змінними
- прізвище
- кіно
Загальною ключовою змінною є прізвище. Ми можемо об'єднати обидві кадри даних і перевірте, що розмірність дорівнює 7×3.
Ми додаємо stringsAsFactors=FALSE у фрейм даних, оскільки не хочемо R перетворити рядки на фактор; змінна повинна залишатися вектором символів. Починаючи з R 4.0.0, це вже значення за замовчуванням для data.frame(), тому аргумент є необов'язковим у новому коді та нешкідливим у старому коді.
# Create origin dataframe( producers <- data.frame( surname = c("Spielberg","Scorsese","Hitchcock","Tarantino","Polanski"), nationality = c("US","US","UK","US","Poland"), stringsAsFactors=FALSE) # Create destination dataframe movies <- data.frame( surname = c("Spielberg", "Scorsese", "Hitchcock", "Hitchcock", "Spielberg", "Tarantino", "Polanski"), title = c("Super 8", "Taxi Driver", "Psycho", "North by Northwest", "Catch Me If You Can", "Reservoir Dogs","Chinatown"), stringsAsFactors=FALSE) # Merge two datasets m1 <- merge(producers, movies, by.x = "surname") m1 dim(m1)
вихід:
surname nationality title 1 Hitchcock UK Psycho 2 Hitchcock UK North by Northwest 3 Polanski Poland Chinatown 4 Scorsese US Taxi Driver 5 Spielberg US Super 8 6 Spielberg US Catch Me If You Can 7 Tarantino US Reservoir Dogs
Давайте об’єднаємо кадри даних, якщо загальні ключові змінні мають різні імена.
Змінюємо прізвище на ім'я у кадрі даних фільмів. Ми використовуємо функцію identical(x1, x2), щоб перевірити, чи ідентичні обидва кадри даних.
# Change name of ` movies ` dataframe colnames(movies)[colnames(movies) == 'surname'] <- 'name' # Merge with different key value m2 <- merge(producers, movies, by.x = "surname", by.y = "name") # Print head of the data head(m2)
вихід:
##surname nationality title ## 1 Hitchcock UK Psycho ## 2 Hitchcock UK North by Northwest ## 3 Polanski Poland Chinatown ## 4 Scorsese US Taxi Driver ## 5 Spielberg US Super 8 ## 6 Spielberg US Catch Me If You Can
# Check if data are identical
identical(m1, m2)
вихід:
## [1] TRUE
Це показує, що операція злиття виконується, навіть якщо імена стовпців різні.
Частковий збіг
Внутрішнє об'єднання вище непомітно відкидає все без відповідного елемента. Не дивно, що два фрейми даних не мають однакових спільних ключових змінних. У повна відповідність, кадр даних повертається тільки рядків, знайдених у кадрі даних x і y. с часткове злиття, можна зберегти рядки без відповідних рядків в іншому кадрі даних. Ці рядки матимуть NA в тих стовпцях, які зазвичай заповнюються значеннями з y. Ми можемо зробити це, встановивши all.x= TRUE.
Наприклад, ми можемо додати нового продюсера, Лукаса, до фрейму даних продюсера без посилань на фільми у фреймі даних фільмів. Якщо ми встановимо all.x= FALSE, R об'єднає лише відповідні значення в обох наборах даних. У нашому випадку продюсер Лукас не буде об'єднаний з результатом, оскільки він відсутній в одному наборі даних.
Давайте подивимося розмірність кожного виводу, коли ми вказуємо all.x= TRUE і коли ми цього не робимо.
# Create a new producer add_producer <- c('Lucas', 'US') # Append it to the ` producer` dataframe producers <- rbind(producers, add_producer) # Use a partial merge m3 <-merge(producers, movies, by.x = "surname", by.y = "name", all.x = TRUE) m3
вихід:
Вивід консолі нижче показує додатковий рядок Lucas, де NA замінює відсутню назву фільму.
# Compare the dimension of each data frame
dim(m1)
вихід:
## [1] 7 3
dim(m2)
вихід:
## [1] 7 3
dim(m3)
вихід:
## [1] 8 3
Як бачимо, новий фрейм даних має розмір 8×3, порівняно з 7×3 для m1 та m2. R заповнює стовпець заголовка значенням NA для Лукаса, продюсера, якому немає відповідного рядка у фреймі даних фільмів.
merge() проти dplyr: об'єднання в R
Базовий R вирішує кожне з'єднання за допомогою однієї функції та набору прапорців. dplyr Натомість пакет надає кожному приєднанню власне дієслово, яке багатьом командам легше читати в конвеєрі.
| Критерії | Базове злиття() | dplyr приєднується |
|---|---|---|
| Вибір об'єднання | all.x / all.y / всі прапорці | Названо в дієслові: left_join(), full_join() |
| Порядок рядків | Сортується за ключем, якщо sort = FALSE | Порядок лівої таблиці зберігається |
| Швидкість на великих кадрах | Повільніше | Загалом швидше |
| Відсутній ключовий стовпець | Збій відбувається із запізненням або об'єднання в неправильних стовпцях | Помилки негайно |
| Залежності | База R, нічого не потрібно встановлювати | Потрібен пакет dplyr |
Два злиття, показані вище, безпосередньо перекладаються у дієслова dplyr:
library(dplyr) # Same inner join as merge(producers, movies, by.x = "surname", by.y = "name") m4 <- inner_join(producers, movies, by = c("surname" = "name")) # Same partial merge as all.x = TRUE m5 <- left_join(producers, movies, by = c("surname" = "name"))
Базовий merge() — безпечніший вибір у пакеті, який не повинен мати залежностей. dplyr — кращий вибір в інтерактивному аналізі, де читабельність та швидкість мають більше значення.
Поширені помилки злиття в R та як їх виправити
Більшість проблем зі злиттям сигналізують про себе як про неочікувану кількість рядків, а не як про повідомлення про помилку, тому перевірка dim() після кожного об'єднання – це звичка, яку варто виробити.
- Результат має більше рядків, ніж будь-який з вхідних даних. Ключ, що повторюється в обох фреймах, створює об'єднання "багато до багатьох", і R повертає кожну комбінацію. Перевірте ключі за допомогою table(duplicated(x$k)) перед об'єднанням.
- Результат порожній. Ключові стовпці зазвичай відрізняються за типом, або один з них містить пробіли. Запустіть str() для обох фреймів та очистіть ключ за допомогою trimws() перед об'єднанням.
- Стовпці повертаються як title.x та title.y. Обидва кадри містять неключовий стовпець з однаковою назвою. Передавайте суфікси = c(“_producer”, “_film”), щоб зробити походження очевидним.
- Рядки більше не знаходяться в початковому порядку. merge() сортує за ключем за замовчуванням. Додайте sort = FALSE або використовуйте явне сортування пізніше.
- Ключове порівняння не відповідає факторам. Порівнюйте символи, а не рівні факторів: обгорніть ключ у as.character() перед об'єднанням фреймів, створених за старих налаштувань R за замовчуванням.
Коли одне й те саме злиття має виконуватися неодноразово, обгорніть його в функція, визначена користувачем тому аргументи не можуть зміщуватися між запусками.


