Συγχώνευση πλαισίων δεδομένων στο R: Πλήρης και μερική αντιστοίχιση
⚡ Έξυπνη Σύνοψη
Η συγχώνευση πλαισίων δεδομένων στο R ενώνει δύο πίνακες σε μία ή περισσότερες στήλες κοινόχρηστου κλειδιού. Η συνάρτηση merge() καλύπτει εσωτερικές, αριστερές, δεξιές και πλήρεις ενώσεις, και αυτή η αναλυτική παρουσίαση δείχνει τόσο μια πλήρη όσο και μια μερική αντιστοίχιση.

Πολύ συχνά, έχουμε δεδομένα από πολλές πηγές. Για να κάνουμε μια ανάλυση, πρέπει συγχώνευση δύο πλαίσια δεδομένων μαζί με ένα ή περισσότερα κοινές μεταβλητές κλειδιού.
Τύποι συγχώνευσης (Join) στην R
Πριν εξετάσουμε τα παραδείγματα, είναι χρήσιμο να γνωρίζουμε ότι η συνάρτηση merge() εκτελεί κάθε τύπο σύνδεσης που αναμένει ένας χρήστης SQL. Η συμπεριφορά ελέγχεται από τα ορίσματα all, all.x και all.y και όχι από διαφορετικό όνομα συνάρτησης.
| Τύπος συμμετοχής | Διατηρούνται σειρές | κλήση συγχώνευσης() | ισοδύναμο dplyr |
|---|---|---|---|
| Εσωτερική ένωση (προεπιλογή) | Μόνο κλειδιά υπάρχουν και στα δύο πλαίσια | συγχώνευση(x, y, από = “k”) | inner_join(x, y, από = “k”) |
| Αριστερή εξωτερική ένωση | Όλες οι γραμμές του x, NA όπου το y δεν έχει καμία αντιστοιχία | συγχώνευση(x, y, από = “k”, all.x = TRUE) | left_join(x, y, από = “k”) |
| Δεξιά εξωτερική ένωση | Όλες οι γραμμές του y, NA όπου το x δεν έχει καμία αντιστοιχία | συγχώνευση(x, y, από = “k”, all.y = TRUE) | right_join(x, y, από = “k”) |
| Πλήρης εξωτερική ένωση | Κάθε γραμμή και από τα δύο πλαίσια | συγχώνευση(x, y, από = “k”, όλα = TRUE) | full_join(x, y, από = “k”) |
| Διασταυρούμενη συμμετοχή | Κάθε συνδυασμός γραμμών | συγχώνευση(x, y, από = NULL) | cross_join(x, y) |
Δύο λεπτομέρειες που αξίζει να θυμάστε πριν από την πρώτη κλήση:
- Αν παραλείψουμε το , η R συγχωνεύεται σε κάθε όνομα στήλης που μοιράζονται τα δύο πλαίσια, κάτι που σπάνια είναι αυτό που θέλουμε.
- Η merge() ταξινομεί το αποτέλεσμα κατά στήλη-κλειδί· η συνάρτηση pass 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
Ας συγχωνεύσουμε πλαίσια δεδομένων όταν οι κοινές μεταβλητές κλειδιού έχουν διαφορετικά ονόματα.
Αλλάζουμε επώνυμο σε όνομα στο πλαίσιο δεδομένων ταινιών. Χρησιμοποιούμε τη συνάρτηση 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.
Για παράδειγμα, μπορούμε να προσθέσουμε έναν νέο παραγωγό, τον Lucas, στο πλαίσιο δεδομένων παραγωγού χωρίς τις αναφορές ταινιών στο πλαίσιο δεδομένων ταινιών. Αν ορίσουμε all.x= FALSE, η R θα ενώσει μόνο τις αντίστοιχες τιμές και στα δύο σύνολα δεδομένων. Στην περίπτωσή μας, ο παραγωγός Lucas δεν θα ενωθεί στο αποτέλεσμα, επειδή λείπει από ένα σύνολο δεδομένων.
Ας δούμε τη διάσταση κάθε εξόδου όταν καθορίζουμε όλα.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 για τον Lucas, τον παραγωγό που δεν έχει αντίστοιχη γραμμή στο πλαίσιο δεδομένων ταινιών.
merge() vs dplyr Ενώσεις στην R
Η βάση R λύνει κάθε σύνδεση με μία συνάρτηση και ένα σύνολο σημαιών. dplyr Το πακέτο δίνει σε κάθε join το δικό του ρήμα, το οποίο πολλές ομάδες βρίσκουν πιο εύκολο να διαβάσουν σε μια διοχέτευση.
| Κριτήρια | Βασική συγχώνευση() | dplyr ενώνει |
|---|---|---|
| Επιλογή της συμμετοχής | all.x / all.y / όλες οι σημαίες | Ονομάζεται στο ρήμα: left_join(), full_join() |
| Σειρά σειρών | Ταξινόμηση κατά κλειδί εκτός εάν η ταξινόμηση = 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.
Όταν η ίδια συγχώνευση πρέπει να εκτελείται επανειλημμένα, τυλίξτε την σε ένα λειτουργία που ορίζεται από το χρήστη επομένως τα ορίσματα δεν μπορούν να μεταβάλλονται μεταξύ των εκτελέσεων.

