Hợp nhất các khung dữ liệu trong R: So khớp toàn bộ và một phần

⚡ Tóm tắt thông minh

Việc hợp nhất các khung dữ liệu trong R kết hợp hai bảng dựa trên một hoặc nhiều cột khóa chung. Hàm merge() bao gồm các phép nối trong, nối trái, nối phải và nối đầy đủ, và hướng dẫn này minh họa cả phép nối khớp hoàn toàn và khớp một phần.

  • 🔑 Các cột chính: Hàm merge() thực hiện phép nối dựa trên by, hoặc dựa trên by.x và by.y khi khóa có tên khác nhau trong mỗi khung hình.
  • 🔗 Trận đấu đầy đủ: Phép nối trong mặc định chỉ giữ lại những hàng có khóa xuất hiện trong cả hai khung dữ liệu.
  • 🧩 Trận đấu một phần: Thiết lập all.x = TRUE sẽ giữ nguyên mọi hàng của khung hình đầu tiên và điền vào các khoảng trống bằng NA.
  • 📐 Kiểm tra kích thước: So sánh dim() trước và sau khi hợp nhất để phát hiện các hàng bị mất hoặc trùng lặp do thao tác nối.
  • ⚙️ Tham gia nhóm Control: Các cờ all, all.x và all.y chọn chế độ hoạt động bên trong, bên trái, bên phải hoặc toàn bộ bên ngoài.
  • 🛠️ Giải pháp thay thế hiện đại: dplyr đặt tên cho mỗi phép nối trong chính động từ và giữ nguyên thứ tự hàng ban đầu.

Hợp nhất các khung dữ liệu trong R

Rất thường xuyên, chúng tôi có dữ liệu từ nhiều nguồn. Để thực hiện phân tích, chúng ta cần hợp nhất hai khung dữ liệu cùng với một hoặc nhiều biến khóa chung.

Các loại phép hợp nhất (ghép nối) trong R

Trước khi xem xét các ví dụ, điều hữu ích là cần biết rằng hàm merge() thực hiện mọi loại phép nối mà người dùng SQL mong đợi. Hành vi này được điều khiển bởi các đối số all, all.x và all.y chứ không phải bởi một tên hàm khác.

Tham gia loại Các hàng được giữ cuộc gọi merge() tương đương dplyr
Phép nối trong (mặc định) Chỉ những khóa xuất hiện trong cả hai khung hình hợp nhất(x, y, theo = “k”) inner_join(x, y, by = “k”)
Kết nối bên ngoài bên trái Tất cả các hàng của x, NA ở những nơi y không có giá trị khớp. merge(x, y, by = “k”, all.x = TRUE) left_join(x, y, by = “k”)
Tham gia bên ngoài bên phải Tất cả các hàng của y, NA ở những nơi x không có giá trị khớp merge(x, y, by = “k”, all.y = TRUE) right_join(x, y, by = “k”)
Tham gia đầy đủ bên ngoài Mỗi hàng từ cả hai khung merge(x, y, by = “k”, all = TRUE) full_join(x, y, by = “k”)
Tham gia chéo Mỗi sự kết hợp của các hàng hợp nhất(x, y, theo = NULL) cross_join(x, y)

Có hai chi tiết đáng nhớ trước cuộc gọi đầu tiên:

  • Việc bỏ qua tham số `by` khiến R hợp nhất các tên cột mà hai khung hình chia sẻ, điều này hiếm khi là điều bạn muốn.
  • Hàm merge() sắp xếp kết quả theo cột khóa; truyền tham số sort = FALSE để giữ nguyên thứ tự ban đầu.

Toàn trận đấu

Một phép so khớp hoàn toàn chỉ trả về các giá trị có tương ứng trong bảng đích. Các hàng không khớp sẽ bị loại bỏ khỏi khung dữ liệu mới. Ngược lại, một phép so khớp một phần sẽ giữ lại các hàng đó và điền các cột bị thiếu bằng NA.

Chúng ta sẽ thấy một cách đơn giản tham gia bên trong. Từ khóa kết nối bên trong chọn các bản ghi có giá trị trùng khớp trong cả hai bảng. Để nối hai tập dữ liệu, chúng ta có thể sử dụng hàm merge(). Chúng ta sẽ sử dụng ba đối số:

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

Ví dụ:

Tạo tập dữ liệu đầu tiên với các biến

  • họ
  • quốc tịch

Tạo tập dữ liệu thứ hai với các biến

  • họ
  • phim

Biến khóa chung là họ. Chúng ta có thể hợp nhất cả hai. khung dữ liệu và kiểm tra xem kích thước có phải là 7×3 hay không.

Chúng tôi thêm stringsAsFactors=FALSE vào khung dữ liệu vì chúng tôi không muốn R để chuyển đổi các chuỗi thành một yếu tố; biến này nên giữ nguyên kiểu dữ liệu là một vectơ ký tự. Từ phiên bản R 4.0.0 trở đi, đây đã là giá trị mặc định cho data.frame(), vì vậy đối số này là tùy chọn trong mã mới và không gây hại trong mã cũ.

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

Đầu ra:

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

Hãy hợp nhất các khung dữ liệu khi các biến khóa chung có tên khác nhau.

Chúng ta đổi họ thành tên trong khung dữ liệu phim. Chúng tôi sử dụng hàm giống hệt nhau (x1, x2) để kiểm tra xem cả hai khung dữ liệu có giống nhau hay không.

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

Đầu ra:

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

Đầu ra:

## [1] TRUE

Điều này cho thấy thao tác hợp nhất được thực hiện ngay cả khi tên cột khác nhau.

Trận đấu một phần

Phép nối trong ở trên đã âm thầm loại bỏ bất cứ thứ gì không có phần tương ứng. Không có gì đáng ngạc nhiên khi hai dataframe không có cùng các biến khóa chung. Trong kết hợp đầy đủ, khung dữ liệu trả về có thể các hàng được tìm thấy trong cả khung dữ liệu x và y. Với sáp nhập một phần, có thể giữ các hàng không có hàng trùng khớp trong khung dữ liệu khác. Các hàng này sẽ có NA trong các cột thường chứa các giá trị từ y. Chúng ta có thể làm điều đó bằng cách đặt all.x= TRUE.

Ví dụ, chúng ta có thể thêm một nhà sản xuất mới, Lucas, vào khung dữ liệu nhà sản xuất mà không cần tham chiếu phim trong khung dữ liệu phim. Nếu ta đặt all.x = FALSE, R sẽ chỉ kết hợp các giá trị khớp nhau trong cả hai tập dữ liệu. Trong trường hợp của chúng ta, nhà sản xuất Lucas sẽ không được kết hợp vào kết quả, vì anh ta bị thiếu trong một tập dữ liệu.

Hãy xem thứ nguyên của từng đầu ra khi chúng ta chỉ định all.x= TRUE và khi không.

# 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

Đầu ra:

Dưới đây là kết quả hiển thị trên bảng điều khiển cho thấy hàng Lucas bổ sung, với NA đại diện cho tiêu đề phim bị thiếu.

Kết quả hiển thị trên bảng điều khiển của quá trình hợp nhất một phần cho thấy Lucas có giá trị NA trong cột tiêu đề.

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

Đầu ra:

## [1] 7 3
dim(m2)

Đầu ra:

## [1] 7 3
dim(m3)

Đầu ra:

## [1] 8 3

Như chúng ta thấy, khung dữ liệu mới có kích thước 8×3, so với 7×3 của m1 và m2. R điền cột tiêu đề bằng NA cho Lucas, nhà sản xuất không có hàng tương ứng trong khung dữ liệu phim.

So sánh hàm `merge()` và `dplyr` trong R.

R cơ bản giải quyết mọi phép nối bằng một hàm và một tập hợp các cờ. dplyr Thay vào đó, gói này gán cho mỗi phép nối một động từ riêng, điều mà nhiều nhóm thấy dễ đọc hơn trong quy trình xử lý dữ liệu.

Tiêu chí Hợp nhất cơ sở() dplyr tham gia
Chọn điểm nối tất cả.x / tất cả.y / tất cả các lá cờ Được đặt tên trong động từ: left_join(), full_join()
Thứ tự hàng Sắp xếp theo khóa trừ khi sort = FALSE Thứ tự của bảng bên trái được giữ nguyên.
Tốc độ trên khung hình lớn Chậm hơn Nói chung là nhanh hơn
Cột khóa bị thiếu Lỗi xảy ra muộn hoặc hợp nhất trên các cột sai. Lỗi ngay lập tức
Sự phụ thuộc Base R, không cần cài đặt gì thêm Yêu cầu gói dplyr.

Hai phép hợp nhất được hiển thị ở trên được dịch trực tiếp thành các động từ 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"))

Hàm `merge()` cơ bản là lựa chọn an toàn hơn bên trong một gói không nên có bất kỳ phụ thuộc nào. `dplyr` là lựa chọn tốt hơn trong phân tích tương tác, nơi khả năng đọc hiểu và tốc độ quan trọng hơn.

Các lỗi hợp nhất thường gặp trong R và cách khắc phục chúng

Hầu hết các vấn đề khi hợp nhất đều thể hiện qua số lượng hàng không như mong đợi chứ không phải thông báo lỗi, vì vậy việc kiểm tra dim() sau mỗi lần nối là một thói quen nên xây dựng.

  • Kết quả có nhiều hàng hơn cả dữ liệu đầu vào lẫn dữ liệu đầu vào. Một khóa lặp lại trong cả hai khung sẽ tạo ra phép nối nhiều-nhiều, và R trả về mọi tổ hợp. Kiểm tra các khóa bằng table(duplicated(x$k)) trước khi hợp nhất.
  • Kết quả trống. Các cột khóa thường khác nhau về kiểu dữ liệu, hoặc một trong số chúng có chứa khoảng trắng ở cuối. Hãy chạy hàm str() trên cả hai khung và làm sạch khóa bằng hàm trimws() trước khi hợp nhất.
  • Các cột được trả về dưới dạng title.x và title.y. Cả hai khung đều chứa một cột không phải khóa có cùng tên. Truyền hậu tố = c(“_producer”, “_film”) để làm rõ nguồn gốc.
  • Các hàng không còn được sắp xếp theo thứ tự ban đầu nữa. Hàm merge() mặc định sắp xếp theo khóa. Thêm sort = FALSE, hoặc sử dụng một loại rõ ràng sau đó
  • Một sự so sánh quan trọng đã thất bại ở các yếu tố. So sánh các ký tự, không phải các cấp độ yếu tố: hãy bọc khóa trong as.character() trước khi hợp nhất các khung được tạo theo các thiết lập mặc định cũ của R.

Khi cần thực hiện cùng một thao tác hợp nhất nhiều lần, hãy gói nó trong một khối lệnh. chức năng do người dùng xác định Vì vậy, các lập luận không thể thay đổi giữa các lần chạy.

Câu Hỏi Thường Gặp

R hợp nhất dựa trên mọi tên cột mà hai khung dữ liệu chia sẻ. Với một cột chung thì điều đó rất thuận tiện; với nhiều cột chung, nó sẽ âm thầm thu hẹp kết quả, và nếu không có cột nào chung thì nó sẽ trả về phép nối chéo. Việc đặt tên khóa một cách rõ ràng sẽ tránh được cả ba trường hợp bất ngờ này.

Không thể thực hiện trong một lệnh merge() duy nhất. Hãy nối các lệnh lại với nhau, hoặc thu gọn danh sách bằng Reduce(function(x, y) merge(x, y, by = “k”), list(df1, df2, df3)). Kiểm tra số lượng hàng sau mỗi bước, vì các khóa trùng lặp sẽ tích lũy rất nhanh.

Cả hai khung đều chứa một cột không phải khóa có cùng tên, vì vậy R sẽ phân biệt chúng. Truyền các hậu tố = c(“_producer”, “_film”) để đặt tên có ý nghĩa cho các bản sao, hoặc loại bỏ cột dư thừa trước khi hợp nhất.

Không. Hàm merge() mặc định sắp xếp kết quả theo cột khóa. Hãy truyền sort = FALSE để giữ nguyên thứ tự dữ liệu đầu vào, hoặc sử dụng một phương pháp khác. dplyr phép nối (join) giúp bảo toàn thứ tự của khung bên trái.

Cung cấp một vectơ: merge(x, y, by = c(“họ”, “năm”)). Khi tên khác nhau, hãy truyền các vectơ khớp nhau cho by.x và by.y. Cả hai vectơ phải liệt kê các cột theo cùng thứ tự.

Sử dụng `by = “row.names”`, hoặc viết tắt `by = 0`. R sẽ thêm lại tên các hàng dưới dạng một cột có tên là `Row.names`, mà bạn thường muốn đổi tên hoặc xóa trước khi tiếp tục phân tích.

Hãy mô tả hai khung dữ liệu và số lượng hàng, và trợ lý AI sẽ chỉ ra các khóa trùng lặp là nguyên nhân có thể xảy ra và đề xuất kiểm tra hàm duplicated(). Hãy xác nhận chẩn đoán bằng dữ liệu của riêng bạn trước khi thay đổi phép nối.

Vâng. RStudio Phiên bản Desktop 2023.09.0 trở lên có tùy chọn cài đặt bổ sung. Trợ lý GitHub Tích hợp này soạn thảo một yêu cầu hợp nhất từ ​​một bình luận. Hãy kiểm tra loại kết nối mà nó chọn, vì một cờ sai sẽ âm thầm thay đổi số lượng hàng.

Tóm tắt bài viết này với: