Злиття кадрів даних у R: повна та часткова відповідність

⚡ Розумний підсумок

Об'єднання фреймів даних у R об'єднує дві таблиці за одним або кількома стовпцями зі спільним ключем. Функція merge() охоплює внутрішнє, ліве, праве та повне об'єднання, і в цьому покроковому посібнику демонструється як повне, так і часткове збіг.

  • 🔑 Ключові колонки: merge() об'єднується з by або з by.x та by.y, коли ключ має різне ім'я в кожному кадрі.
  • 🔗 Повний матч: Внутрішнє об'єднання за замовчуванням зберігає лише рядки, ключ яких з'являється в обох фреймах даних.
  • 🧩 Частковий збіг: Встановлення all.x = TRUE зберігає кожен рядок першого кадру та заповнює пробіли значенням NA.
  • 📐 Перевірка розмірів: Порівняйте dim() до та після об'єднання, щоб виявити рядки, втрачені або продубльовані об'єднанням.
  • ️ Приєднатися до керування: Прапорці all, all.x та all.y вибирають внутрішню, ліву, праву або повністю зовнішню поведінку.
  • 🛠️ Сучасна альтернатива: dplyr імена кожного об'єднання в самому дієслові та зберігає початковий порядок рядків.

Об’єднати кадри даних у R

Дуже часто ми маємо дані з кількох джерел. Щоб провести аналіз, нам потрібно злиття два кадри даних разом з одним або кількома загальні ключові змінні.

Типи злиття (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 замінює відсутню назву фільму.

Вивід консолі часткового злиття, що показує 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 за замовчуванням.

Коли одне й те саме злиття має виконуватися неодноразово, обгорніть його в функція, визначена користувачем тому аргументи не можуть зміщуватися між запусками.

Поширені запитання

R виконує об'єднання для кожного імені стовпця, яке спільно використовують два фрейми. З одним спільним стовпцем це зручно; з кількома він непомітно звужує результат, а якщо немає, повертає перехресне з'єднання. Чітке найменування ключа дозволяє уникнути всіх трьох несподіванок.

Не в одному виклику merge(). З'єднайте виклики в ланцюжок або згорніть список за допомогою Reduce(function(x, y) merge(x, y, by = “k”), list(df1, df2, df3)). Перевіряйте кількість рядків після кожного кроку, оскільки дублікати ключів швидко накопичуються.

Обидва кадри містили неключовий стовпець з однаковою назвою, тому R усуває їх неоднозначність. Передавайте суфікси = c(“_producer”, “_film”), щоб надати копіям змістовні назви, або видаліть надлишковий стовпець перед об’єднанням.

Ні. merge() сортує результат за ключовим стовпцем за замовчуванням. Передайте sort = FALSE, щоб зберегти порядок вхідних значень, або використовуйте dplyr об'єднання, яке зберігає порядок лівого фрейму.

Введіть вектор: merge(x, y, by = c(“прізвище”, “рік”)). Якщо імена відрізняються, передайте відповідні вектори до by.x та by.y. Обидва вектори повинні перераховувати стовпці в одному порядку.

Використовуйте by = “row.names” або скорочений запис by = 0. R додає назви рядків назад як стовпець під назвою Row.names, який зазвичай потрібно перейменувати або видалити перед продовженням аналізу.

Опишіть два фрейми та кількість рядків, і помічник зі штучним інтелектом вкаже на дублікати ключів як ймовірну причину та запропонує перевірку duplicated(). Підтвердьте діагноз на основі власних даних, перш ніж змінювати об'єднання.

Так. RStudio Desktop 2023.09.0 та пізніших версій постачається з можливістю згоди. Копілот GitHub інтеграція, яка створює чернетку злиття з коментаря. Перевірте вибраний тип об'єднання, оскільки неправильний прапорець непомітно змінює кількість рядків.

Підсумуйте цей пост за допомогою: