Slå samman dataramar i R: Full och partiell matchning
⚡ Smart sammanfattning
Att sammanfoga dataramar i R sammanfogar två tabeller på en eller flera kolumner med delade nyckelringar. Funktionen merge() täcker inner-, vänster-, höger- och fullständiga kopplingar, och den här genomgången demonstrerar både en fullständig matchning och en partiell matchning.

Mycket ofta har vi data från flera källor. För att göra en analys måste vi göra det sammanfoga två dataramar tillsammans med en eller flera vanliga nyckelvariabler.
Typer av sammanslagningar (Join) i R
Innan du går igenom exemplen är det bra att veta att merge() utför alla join-typer som en SQL-användare förväntar sig. Beteendet styrs av argumenten all, all.x och all.y snarare än av ett annat funktionsnamn.
| Gå med typ | Rader behållna | merge()-anrop | dplyr-ekvivalent |
|---|---|---|---|
| Inre koppling (standard) | Endast nycklar finns i båda ramarna | sammanfoga(x, y, by = “k”) | inner_join(x, y, by = “k”) |
| Vänster yttre skarv | Alla rader av x, NA där y inte har någon matchning | merge(x, y, by = "k", all.x = TRUE) | vänster_join(x, y, by = “k”) |
| Höger yttre fog | Alla rader i y, NA där x inte har någon matchning | merge(x, y, by = "k", all.y = TRUE) | höger_join(x, y, by = “k”) |
| Full ytterskarv | Varje rad från båda ramarna | merge(x, y, by = "k", all = TRUE) | full_join(x, y, by = “k”) |
| Kors gå med | Varje kombination av rader | merge(x, y, by = NULL) | korskoppling(x, y) |
Två detaljer är värda att komma ihåg före det första samtalet:
- Om du utelämnar 'by' görs R-sammanslagning på varje kolumnnamn som de två ramarna delar, vilket sällan är vad man vill.
- merge() sorterar resultatet efter nyckelkolumnen; använd sort = FALSE för att behålla den inkommande ordningen.
Hel match
En fullständig matchning returnerar endast de värden som har en motsvarighet i måltabellen. Rader utan matchning tas bort från den nya dataframen. En partiell matchning, däremot, behåller dessa rader och fyller de saknade kolumnerna med NA.
Vi kommer att se en enkel inre koppling. Nyckelordet inre join väljer poster som har matchande värden i båda tabellerna. För att sammanfoga två datamängder kan vi använda funktionen merge(). Vi kommer att använda tre argument:
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
Exempel:
Skapa första datamängden med variabler
- efternamn
- nationalitet
Skapa en andra datamängd med variabler
- efternamn
- filmer
Den gemensamma nyckelvariabeln är efternamn. Vi kan slå samman båda dataramar och kontrollera att dimensionen är 7×3.
Vi lägger till stringsAsFactors=FALSE i dataframen eftersom vi inte vill R att omvandla strängarna till en faktor; variabeln bör förbli en teckenvektor. Sedan R 4.0.0 är detta redan standard för data.frame(), så argumentet är valfritt i ny kod och ofarligt i gammal kod.
# 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)
Produktion:
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
Låt oss slå samman dataramar när de vanliga nyckelvariablerna har olika namn.
Vi byter efternamn till namn i filmens dataram. Vi använder funktionen identisk(x1, x2) för att kontrollera om båda dataramarna är identiska.
# 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)
Produktion:
##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)
Produktion:
## [1] TRUE
Detta visar att sammanslagningsoperationen utförs även om kolumnnamnen är olika.
Delvis matchning
Den inre kopplingen ovan tappade tyst allt utan en motsvarighet. Det är inte förvånande att två dataframes inte har samma gemensamma nyckelvariabler. I full matchning, returnerar dataramen endast rader som finns i både x- och y-dataramen. Med partiell sammanslagning, är det möjligt att behålla raderna utan matchande rader i den andra dataramen. Dessa rader kommer att ha NA i de kolumner som vanligtvis är fyllda med värden från y. Vi kan göra det genom att ställa in all.x= TRUE.
Till exempel kan vi lägga till en ny producent, Lucas, i producentens dataframe utan filmreferenserna i filmernas dataframe. Om vi sätter all.x = FALSE kommer R endast att koppla samman de matchande värdena i båda datamängderna. I vårt fall kommer producenten Lucas inte att kopplas till resultatet, eftersom han saknas i en datamängd.
Låt oss se dimensionen för varje utdata när vi anger all.x= TRUE och när vi inte gör det.
# 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
Produktion:
Konsolutgången nedan visar den extra Lucas-raden, där NA står för den saknade filmtiteln.
# Compare the dimension of each data frame
dim(m1)
Produktion:
## [1] 7 3
dim(m2)
Produktion:
## [1] 7 3
dim(m3)
Produktion:
## [1] 8 3
Som vi kan se är den nya dataframen 8×3, jämfört med 7×3 för m1 och m2. R fyller titelkolumnen med NA för Lucas, producenten som inte har någon matchande rad i filmens dataframe.
merge() vs dplyr Joins i R
Base R löser varje join med en funktion och en uppsättning flaggor. dplyr paketet ger istället varje join sitt eget verb, vilket många team tycker är lättare att läsa i en pipeline.
| Kriterier | Bassammanslagning() | dplyr-anslutningar |
|---|---|---|
| Att välja koppling | all.x / all.y / alla flaggor | Namngivet i verbet: left_join(), full_join() |
| Radordning | Sorteras efter nyckel om inte sortering = FALSKT | Ordningen i den vänstra tabellen bevaras |
| Hastighet på stora bildrutor | Långsammare | Generellt snabbare |
| Saknad nyckelkolumn | Misslyckas sent eller sammanfogas på fel kolumner | Fel omedelbart |
| beroenden | Bas R, inget att installera | Kräver dplyr-paketet |
De två sammanslagningarna som visas ovan översätts direkt till dplyr-verb:
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"))
Base merge() är det säkrare valet i ett paket som inte ska ha några beroenden. dplyr är det bättre valet i en interaktiv analys, där läsbarhet och hastighet är viktigare.
Vanliga sammanslagningsfel i R och hur man åtgärdar dem
De flesta sammanslagningsproblem anger sig själva som ett oväntat radantal snarare än ett felmeddelande, så att kontrollera dim() efter varje sammankoppling är en vana värd att bygga upp.
- Resultatet har fler rader än någon av indatavärdena. En nyckel som upprepas i båda ramarna producerar en många-till-många-koppling, och R returnerar varje kombination. Kontrollera nycklarna med table(duplicated(x$k)) innan de sammanfogas.
- Resultatet är tomt. Nyckelkolumnerna skiljer sig vanligtvis åt i typ, eller så har en av dem mellanslag. Kör str() på båda ramarna och rensa nyckeln med trimws() innan sammanfogningen.
- Kolumner återkommer som title.x och title.y. Båda bildrutorna har en icke-nyckelkolumn med samma namn. Skicka suffix = c("_producer", "_film") för att göra ursprunget uppenbart.
- Raderna är inte längre i sin ursprungliga ordning. merge() sorterar på nyckeln som standard. Lägg till sort = FALSE, eller använd en explicit sort efteråt.
- En viktig jämförelse misslyckas med faktorer. Jämför tecken, inte faktornivåer: linda in nyckeln i as.character() innan ramar som skapats under äldre R-standardvärden sammanfogas.
När samma sammanslagning måste köras upprepade gånger, linda in den i en användardefinierad funktion så argumenten kan inte glida mellan körningarna.

