Обединяване на кадри с данни в R: пълно и частично съвпадение
⚡ Умно обобщение
Сливането на рамки с данни в R свързва две таблици по една или повече колони със споделен ключ. Функцията merge() обхваща вътрешни, леви, десни и пълни съединения, а това ръководство демонстрира както пълно, така и частично съвпадение.

Много често имаме данни от множество източници. За да извършим анализ, трябва да се сливат две рамки с данни заедно с една или повече общи ключови променливи.
Видове сливания (Join) в R
Преди да разгледаме примерите, е полезно да знаем, че merge() изпълнява всеки тип съединение, който един SQL потребител очаква. Поведението се контролира от аргументите all, all.x и all.y, а не от различно име на функция.
| Тип присъединяване | Редовете са запазени | извикване на merge() | еквивалент на dplyr |
|---|---|---|---|
| Вътрешно съединение (по подразбиране) | Само ключове, присъстващи и в двата кадъра | сливане(x, y, от = „k“) | вътрешно_съединяване(x, y, от = „k“) |
| Ляво външно съединение | Всички редове на x, NA, където y няма съвпадение | сливане(x, y, от = „k“, всички.x = TRUE) | ляво_съединяване(x, y, от = „k“) |
| Десен външен съединител | Всички редове на y, NA, където x няма съвпадение | сливане(x, y, от = „k“, всички.y = TRUE) | right_join(x, y, от = „k“) |
| Пълно външно съединяване | Всеки ред от двата кадъра | сливане(x, y, от = „k“, всички = TRUE) | пълно_съединяване(x, y, от = „k“) |
| Кръстосано присъединяване | Всяка комбинация от редове | сливане(x, y, от = NULL) | кръстосано_съединяване(x, y) |
Две подробности, които си струва да запомните преди първото обаждане:
- Пропускането на „by“ кара R да се слива с всяко име на колона, което двете рамки споделят, което рядко е това, което искате.
- merge() сортира резултата по ключовата колона; подайте sort = FALSE, за да запазите входящия ред.
Пълен мач
Пълното съвпадение връща само стойностите, които имат еквивалент в целевата таблица. Редовете без съвпадение се премахват от новия кадър с данни. Частичното съвпадение, за разлика от това, запазва тези редове и запълва липсващите колони с NA.
Ще видим просто вътрешно присъединяване. Ключовата дума 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.
Когато едно и също сливане трябва да се изпълнява многократно, увийте го в потребителски дефинирана функция така че аргументите не могат да се отклоняват между изпълненията.

