Spajanje okvira podataka u R: potpuno i djelomično podudaranje

⚡ Pametni sažetak

Spajanje podatkovnih okvira u R-u spaja dvije tablice na jednom ili više stupaca s dijeljenim ključem. Funkcija merge() pokriva unutarnje, lijevo, desno i potpuno spajanje, a ovaj vodič demonstrira i potpuno i djelomično podudaranje.

  • 🔑 Ključni stupci: merge() se spaja na by ili na by.x i by.y kada ključ nosi drugačije ime u svakom okviru.
  • 🔗 Cijela utakmica: Zadani unutarnji spoj zadržava samo retke čiji se ključ pojavljuje u oba okvira podataka.
  • 🧩 Djelomično podudaranje: Postavljanjem all.x = TRUE zadržava se svaki redak prvog okvira, a praznine popunjava s NA.
  • 📐 Provjera dimenzija: Usporedite dim() prije i poslije spajanja kako biste uhvatili retke izgubljene ili duplicirane spajanjem.
  • Pridruži se kontroli: Zastavice all, all.x i all.y odabiru unutarnje, lijevo, desno ili potpuno vanjsko ponašanje.
  • 🛠️ Moderna alternativa: dplyr imena se spajaju u samom glagolu i čuvaju izvorni redoslijed redaka.

Spajanje okvira podataka u R

Vrlo često imamo podatke iz više izvora. Da bismo izvršili analizu, moramo spojiti dva podatkovna okvira zajedno s jednim ili više zajedničke ključne varijable.

Vrste spajanja (Join) u R-u

Prije nego što prođemo kroz primjere, korisno je znati da merge() izvršava svaku vrstu spajanja koju SQL korisnik očekuje. Ponašanje je kontrolirano argumentima all, all.x i all.y, a ne drugim nazivom funkcije.

Vrsta pridruživanja Redci sačuvani merge() poziv ekvivalent dplyr-a
Unutarnji spoj (zadano) Samo ključevi prisutni u oba okvira spajanje(x, y, s = “k”) unutarnji_spajanje(x, y, by = “k”)
Lijevi vanjski spoj Svi retci x, NA gdje y nema podudaranja spajanje(x, y, po = “k”, sve.x = ISTINA) lijevo_spajanje(x, y, by = “k”)
Desni vanjski spoj Svi retci y, NA gdje x nema podudaranja spajanje(x, y, by = “k”, sve.y = ISTINA) desno_spajanje(x, y, by = “k”)
Potpuni vanjski spoj Svaki red iz oba okvira spajanje(x, y, od = “k”, sve = ISTINA) puni_spajanje(x, y, by = “k”)
Unakrsno spajanje Svaka kombinacija redova spajanje(x, y, s = NULL) cross_join(x, y)

Prije prvog poziva vrijedi zapamtiti dva detalja:

  • Izostavljanje "by" uzrokuje spajanje R-a na svakom nazivu stupca koji dva okvira dijele, što rijetko želite.
  • merge() sortira rezultat prema ključnom stupcu; proslijedite sort = FALSE kako biste zadržali dolazni redoslijed.

Potpuna utakmica

Potpuno podudaranje vraća samo vrijednosti koje imaju ekvivalent u odredišnoj tablici. Redci bez podudaranja izbacuju se iz novog okvira podataka. Djelomično podudaranje, nasuprot tome, zadržava te retke i popunjava nedostajuće stupce s NA.

Vidjet ćemo jednostavan unutarnji spoj. Ključna riječ unutarnje spajanje odabire zapise koji imaju podudarne vrijednosti u obje tablice. Za spajanje dva skupa podataka možemo koristiti funkciju merge(). Koristit ćemo tri argumenta:

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

Primjer:

Stvorite prvi skup podataka s varijablama

  • prezime
  • državljanstvo

Stvorite drugi skup podataka s varijablama

  • prezime
  • filmovi

Zajednička ključna varijabla je prezime. Možemo spojiti oboje podatkovni okviri i provjerite je li dimenzionalnost 7×3.

U podatkovni okvir dodajemo stringsAsFactors=FALSE jer ne želimo R pretvoriti nizove u faktor; varijabla bi trebala ostati vektor znakova. Od verzije R 4.0.0 ovo je već zadana vrijednost za data.frame(), pa je argument opcionalan u novom kodu, a bezopasan u starom kodu.

# 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)

Izlaz:

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

Spojimo podatkovne okvire kada varijable zajedničkog ključa imaju različita imena.

Mijenjamo prezime u ime u podatkovnom okviru filmova. Koristimo funkciju identical(x1, x2) da provjerimo jesu li oba podatkovna okvira identična.

# 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)

Izlaz:

##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)

Izlaz:

## [1] TRUE

Ovo pokazuje da se operacija spajanja izvodi čak i ako su nazivi stupaca različiti.

Djelomično podudaranje

Unutarnji spoj iznad tiho je odbacio sve bez ekvivalenta. Nije iznenađujuće da dva podatkovna okvira nemaju iste zajedničke ključne varijable. U potpuno podudaranje, dataframe se vraća samo redaka koji se nalaze i u x i u podatkovnom okviru. S djelomično spajanje, moguće je zadržati retke bez odgovarajućih redaka u drugom okviru podataka. Ovi redovi će imati NA u onim stupcima koji su obično ispunjeni vrijednostima iz y. To možemo učiniti postavljanjem all.x= TRUE.

Na primjer, možemo dodati novog producenta, Lucasa, u okvir podataka producenta bez referenci filmova u okviru podataka filmova. Ako postavimo all.x= FALSE, R će spojiti samo odgovarajuće vrijednosti u oba skupa podataka. U našem slučaju, producent Lucas neće biti spojen u rezultat jer nedostaje u jednom skupu podataka.

Pogledajmo dimenziju svakog izlaza kada specificiramo all.x= TRUE i kada ne specificiramo.

# 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

Izlaz:

Izlaz konzole ispod prikazuje dodatni Lucasov redak, gdje NA zamjenjuje nedostajući naslov filma.

Izlaz konzole djelomičnog spajanja koji prikazuje Lucasa s NA u stupcu naslova

# Compare the dimension of each data frame
dim(m1)

Izlaz:

## [1] 7 3
dim(m2)

Izlaz:

## [1] 7 3
dim(m3)

Izlaz:

## [1] 8 3

Kao što vidimo, novi podatkovni okvir je 8×3, u usporedbi sa 7×3 za m1 i m2. R ispunjava stupac naslova s ​​NA za Lucasa, producenta koji nema odgovarajući redak u podatkovnom okviru filma.

merge() vs. dplyr Spajanja u R-u

Bazni R rješava svaki spoj s jednom funkcijom i skupom zastavica. dplyr Paket umjesto toga daje svakom spajanju vlastiti glagol, što mnogi timovi smatraju lakšim za čitanje u cjevovodu.

Kriteriji Spajanje baze() dplyr spajanja
Odabir spoja sve.x / sve.y / sve zastavice Imenovano u glagolu: left_join(), full_join()
Redoslijed redaka Sortirano po ključu osim ako sort = FALSE Redoslijed lijeve tablice je sačuvan
Brzina na velikim okvirima sporiji Općenito brže
Nedostaje ključni stupac Kasno ne uspijeva ili se spaja u pogrešnim stupcima Greške odmah
ovisnosti Baza R, nema što instalirati Zahtijeva dplyr paket

Dva gore prikazana spajanja prevode se direktno u dplyr glagole:

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"))

Osnovna merge() je sigurniji izbor unutar paketa koji ne bi trebao imati ovisnosti. dplyr je bolji izbor u interaktivnoj analizi, gdje su čitljivost i brzina važniji.

Uobičajene pogreške spajanja u R-u i kako ih ispraviti

Većina problema spajanja se najavljuje kao neočekivani broj redaka, a ne kao poruka o pogrešci, stoga je provjera dim() nakon svakog spajanja navika koju vrijedi steći.

  • Rezultat ima više redaka od bilo kojeg ulaza. Ključ koji se ponavlja u oba okvira stvara spajanje više-na-više, a R vraća svaku kombinaciju. Pregledajte ključeve pomoću table(duplicated(x$k)) prije spajanja.
  • Rezultat je prazan. Ključni stupci se obično razlikuju po vrsti ili jedan od njih sadrži razmake na kraju. Pokrenite str() na oba okvira i očistite ključ pomoću trimws() prije spajanja.
  • Kolumne se vraćaju kao naslov.x i naslov.y. Oba okvira nose stupac koji nije ključan s istim imenom. Dodajte sufikse = c(“_producer”, “_film”) kako bi porijeklo bilo očito.
  • Redovi više nisu u izvornom redoslijedu. merge() sortira po ključu prema zadanim postavkama. Dodajte sort = FALSE ili upotrijebite eksplicitno sortiranje nakon toga.
  • Ključna usporedba ne uspijeva na temelju faktora. Usporedite znakove, a ne razine faktorizacije: ključ se stavi u as.character() prije spajanja okvira stvorenih pod starijim R zadanim postavkama.

Kada se isto spajanje mora ponavljati, zamotajte ga u korisnički definirana funkcija tako da argumenti ne mogu lutati između prolazaka.

Pitanja i odgovori

R spaja svaki naziv stupca koji dva okvira dijele. S jednim zajedničkim stupcem to je praktično; s nekoliko tiho sužava rezultat, a bez ijednog vraća unakrsno spajanje. Eksplicitno imenovanje ključa izbjegava sva tri iznenađenja.

Ne u jednom pozivu merge(). Lančano povežite pozive ili savijte listu s Reduce(function(x, y) merge(x, y, by = “k”), list(df1, df2, df3)). Provjerite broj redaka nakon svakog koraka, jer se duplicirani ključevi brzo spajaju.

Oba okvira su nosila neključni stupac s istim imenom, pa ih R uklanja dvosmislenost. Dodajte sufikse = c(“_producer”, “_film”) kako biste kopijama dali smislena imena ili uklonite redundantni stupac prije spajanja.

Ne. merge() sortira rezultat prema zadanim postavkama. Proslijedite sort = FALSE da biste zadržali dolazni redoslijed ili upotrijebite dplyr spoj, koji čuva redoslijed lijevog okvira.

Navedite vektor: merge(x, y, by = c(“prezime”, “godina”)). Kada se imena razlikuju, proslijedite odgovarajuće vektore u by.x i by.y. Oba vektora moraju navesti stupce istim redoslijedom.

Koristite by = “row.names” ili skraćenicu by = 0. R dodaje nazive redaka natrag kao stupac pod nazivom Row.names, koji obično želite preimenovati ili izbaciti prije nastavka analize.

Opišite dva okvira i broj redaka, a AI asistent će ukazati na duplicirane ključeve kao vjerojatni uzrok i predložiti provjeru duplicated(). Potvrdite dijagnozu u odnosu na vlastite podatke prije promjene spajanja.

Da. RStudio Desktop 2023.09.0 i novije verzije isporučuju se s opcijom prijave GitHub kopilot integracija koja iz komentara izrađuje nacrt spajanja. Provjerite vrstu spajanja koju odabere, jer pogrešna zastavica tiho mijenja broj redaka.

Sažmite ovu objavu uz: