Объединение кадров данных в R: полное и частичное совпадение

⚡ Умное резюме

В R объединение таблиц данных осуществляется по одному или нескольким общим ключевым столбцам. Функция merge() описывает внутренние, левые, правые и полные объединения, и в этом пошаговом руководстве показаны как полное, так и частичное совпадение.

  • 🔑 Основные столбцы: Функция merge() объединяет данные по by или по by.x и by.y, если ключ имеет разное имя в каждом кадре.
  • 🔗 Полное совпадение: При использовании внутреннего соединения по умолчанию сохраняются только те строки, ключ которых присутствует в обоих фреймах данных.
  • 🧩 Частичное совпадение: Установка параметра all.x = TRUE сохраняет все строки первого кадра и заполняет пробелы значениями NA.
  • 📐 Проверка размеров: Сравните значения функции dim() до и после слияния, чтобы выявить строки, потерянные или продублированные в результате объединения.
  • ⚙️ Управление объединением: Флаги all, all.x и all.y позволяют выбрать внутреннее, левое, правое или полностью внешнее поведение.
  • 🇧🇷 Современная альтернатива: Функция dplyr присваивает каждому соединению имя непосредственно в самом глаголе и сохраняет исходный порядок строк.

Объединение кадров данных в R

Очень часто у нас есть данные из нескольких источников. Для проведения анализа нам необходимо слияние два фрейма данных вместе с одним или несколькими общие ключевые переменные.

Типы операций слияния (объединения) в R

Прежде чем приступать к примерам, полезно знать, что функция merge() выполняет все типы объединений, ожидаемые пользователем SQL. Ее поведение контролируется аргументами all, all.x и all.y, а не другим именем функции.

Тип соединения Сохранены ряды вызов функции merge() эквивалент dplyr
Внутреннее соединение (по умолчанию) В обоих кадрах присутствуют только ключи. merge(x, y, by = “k”) inner_join(x, y, by = “k”)
Левое внешнее соединение Все строки x, NA, в которых y не имеет совпадений. merge(x, y, by = “k”, all.x = TRUE) left_join(x, y, by = “k”)
Правое внешнее соединение Все строки y, NA, где x не имеет соответствия merge(x, y, by = “k”, all.y = TRUE) right_join(x, y, by = “k”)
Полное внешнее соединение Каждая строка из обоих фреймов merge(x, y, by = “k”, all = TRUE) full_join(x, y, by = “k”)
Перекрестное соединение Каждая комбинация строк merge(x, y, by = NULL) cross_join(x, y)

Перед первым звонком стоит помнить о двух вещах:

  • Если не использовать предлог "by", R выполнит слияние по каждому имени столбца, которое используется в двух фреймах, что редко бывает нужно.
  • Функция merge() сортирует результат по ключевому столбцу; передайте sort = FALSE, чтобы сохранить порядок входящих данных.

Полное совпадение

Полное совпадение возвращает только те значения, которые имеют аналог в целевой таблице. Строки без совпадения удаляются из нового фрейма данных. Частичное совпадение, напротив, сохраняет эти строки и заполняет отсутствующие столбцы значениями NA.

Мы увидим простой внутреннее соединение. Ключевое слово внутреннего соединения выбирает записи, имеющие совпадающие значения в обеих таблицах. Чтобы объединить два набора данных, мы можем использовать функцию 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

Давайте объединим фреймы данных, когда общие ключевые переменные имеют разные имена.

Мы меняем фамилию на имя в кадре данных фильмов. Мы используем функцию идентичных (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 заполняет столбец title значениями NA для Лукаса, продюсера, у которого нет соответствующей строки во фрейме данных movies.

Сравнение функций merge() и dplyr в R.

В базовом R каждое соединение решается с помощью одной функции и набора флагов. дплир Вместо этого пакет предоставляет каждому соединению свой собственный глагол, что, по мнению многих команд, упрощает чтение данных в конвейере.

Критерии Base merge() dplyr объединяет
Выбор способа присоединения все.x / все.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. В обоих кадрах есть неключевой столбец с одинаковым именем. Передайте suffixes = c(“_producer”, “_film”), чтобы сделать происхождение очевидным.
  • Строки больше не расположены в исходном порядке. Функция merge() по умолчанию сортирует по ключу. Добавьте sort = FALSE или используйте явный вид в конце.
  • Ключевое сравнение не учитывает ряд факторов. Сравнивайте символы, а не уровни факторов: перед объединением фреймов, созданных в соответствии со старыми настройками R по умолчанию, заключите ключ в функцию as.character().

Если одно и то же слияние необходимо выполнять многократно, оберните его в определяемая пользователем функция Таким образом, аргументы не могут изменяться между запусками.

Часто задаваемые вопросы (FAQ)

В R объединение выполняется по каждому имени столбца, общему для двух фреймов. При наличии одного общего столбца это удобно; при наличии нескольких он незаметно сужает результат, а при отсутствии — возвращает перекрестное соединение. Явное указание ключа позволяет избежать всех трех неожиданностей.

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

В обоих фреймах присутствовал неключевой столбец с одинаковым именем, поэтому R устраняет неоднозначность. Передайте suffixes = c(“_producer”, “_film”), чтобы присвоить копиям осмысленные имена, или удалите избыточный столбец перед слиянием.

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

Передайте вектор: merge(x, y, by = c(“surname”, “year”)). Если имена различаются, передайте совпадающие векторы в by.x и by.y. Оба вектора должны перечислять столбцы в одном и том же порядке.

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

Опишите два фрейма и количество строк, и ИИ-помощник укажет на повторяющиеся ключи как на вероятную причину и предложит проверить их с помощью функции duplicated(). Перед изменением операции объединения подтвердите диагноз, сравнив его с вашими собственными данными.

Да. RStudio В настольных версиях 2023.09.0 и более поздних версиях доступна опция подключения по желанию. Второй пилот GitHub Интеграция, которая формирует запрос на слияние на основе комментария. Проверьте тип соединения, который она выбирает, поскольку неправильный флаг незаметно изменяет количество строк.

Подведем итог этой публикации следующим образом: