Có thể liên kết hai khung dữ liệu không có cùng một tập hợp các cột không? Tôi hy vọng sẽ giữ lại các cột không phù hợp sau khi liên kết.Kết hợp hai khung dữ liệu theo hàng (rbind) khi chúng có các nhóm cột khác nhau
Trả lời
rbind.fill
từ gói plyr
có thể là những gì bạn đang tìm kiếm.
Bạn có thể sử dụng smartbind
từ gói gtools
.
Ví dụ:
library(gtools)
df1 <- data.frame(a = c(1:5), b = c(6:10))
df2 <- data.frame(a = c(11:15), b = c(16:20), c = LETTERS[1:5])
smartbind(df1, df2)
# result
a b c
1.1 1 6 <NA>
1.2 2 7 <NA>
1.3 3 8 <NA>
1.4 4 9 <NA>
1.5 5 10 <NA>
2.1 11 16 A
2.2 12 17 B
2.3 13 18 C
2.4 14 19 D
2.5 15 20 E
Tôi đã thử 'smartbind' với hai khung dữ liệu lớn (tổng cộng khoảng 3 * 10^6 hàng) và hủy bỏ sau 10 phút. – Joe
Bạn cũng có thể chỉ cần kéo ra khỏi các tên cột chung.
> cols <- intersect(colnames(df1), colnames(df2))
> rbind(df1[,cols], df2[,cols])
Nếu các cột trong df1 là một tập hợp con của những người trong df2 (bởi tên cột):
df3 <- rbind(df1, df2[, names(df1)])
Có lẽ tôi hoàn toàn hiểu sai câu hỏi của bạn, nhưng "Tôi hy vọng có thể giữ lại các cột mà không phù hợp sau khi ràng buộc "làm cho tôi nghĩ rằng bạn đang tìm kiếm một left join
hoặc right join
tương tự như một truy vấn SQL. R có chức năng merge
cho phép bạn chỉ định các kết nối bên trái, phải hoặc bên trong tương tự như nối các bảng trong SQL.
Hiện đã là một câu hỏi lớn và trả lời về chủ đề này ở đây: How to join (merge) data frames (inner, outer, left, right)?
Tôi đã viết một chức năng để làm điều này vì tôi thích mã của tôi để cho tôi biết nếu có điều gì là sai. Hàm này sẽ cho bạn biết rõ ràng tên cột nào không khớp và nếu bạn có loại không phù hợp. Sau đó, nó sẽ làm tốt nhất của nó để kết hợp data.frames anyway. Giới hạn là bạn chỉ có thể kết hợp hai data.frames tại một thời điểm.
### combines data frames (like rbind) but by matching column names
# columns without matches in the other data frame are still combined
# but with NA in the rows corresponding to the data frame without
# the variable
# A warning is issued if there is a type mismatch between columns of
# the same name and an attempt is made to combine the columns
combineByName <- function(A,B) {
a.names <- names(A)
b.names <- names(B)
all.names <- union(a.names,b.names)
print(paste("Number of columns:",length(all.names)))
a.type <- NULL
for (i in 1:ncol(A)) {
a.type[i] <- typeof(A[,i])
}
b.type <- NULL
for (i in 1:ncol(B)) {
b.type[i] <- typeof(B[,i])
}
a_b.names <- names(A)[!names(A)%in%names(B)]
b_a.names <- names(B)[!names(B)%in%names(A)]
if (length(a_b.names)>0 | length(b_a.names)>0){
print("Columns in data frame A but not in data frame B:")
print(a_b.names)
print("Columns in data frame B but not in data frame A:")
print(b_a.names)
} else if(a.names==b.names & a.type==b.type){
C <- rbind(A,B)
return(C)
}
C <- list()
for(i in 1:length(all.names)) {
l.a <- all.names[i]%in%a.names
pos.a <- match(all.names[i],a.names)
typ.a <- a.type[pos.a]
l.b <- all.names[i]%in%b.names
pos.b <- match(all.names[i],b.names)
typ.b <- b.type[pos.b]
if(l.a & l.b) {
if(typ.a==typ.b) {
vec <- c(A[,pos.a],B[,pos.b])
} else {
warning(c("Type mismatch in variable named: ",all.names[i],"\n"))
vec <- try(c(A[,pos.a],B[,pos.b]))
}
} else if (l.a) {
vec <- c(A[,pos.a],rep(NA,nrow(B)))
} else {
vec <- c(rep(NA,nrow(A)),B[,pos.b])
}
C[[i]] <- vec
}
names(C) <- all.names
C <- as.data.frame(C)
return(C)
}
rbind.ordered=function(x,y){
diffCol = setdiff(colnames(x),colnames(y))
if (length(diffCol)>0){
cols=colnames(y)
for (i in 1:length(diffCol)) y=cbind(y,NA)
colnames(y)=c(cols,diffCol)
}
diffCol = setdiff(colnames(y),colnames(x))
if (length(diffCol)>0){
cols=colnames(x)
for (i in 1:length(diffCol)) x=cbind(x,NA)
colnames(x)=c(cols,diffCol)
}
return(rbind(x, y[, colnames(x)]))
}
gtools/didnt smartbind như làm việc với Ngày, có lẽ vì nó được as.vectoring. Vì vậy, đây là giải pháp của tôi ...
sbind = function(x, y, fill=NA) {
sbind.fill = function(d, cols){
for(c in cols)
d[[c]] = fill
d
}
x = sbind.fill(x, setdiff(names(y),names(x)))
y = sbind.fill(y, setdiff(names(x),names(y)))
rbind(x, y)
}
Một giải pháp gần đây hơn là sử dụng dplyr
's bind_rows
chức năng mà tôi giả định là hiệu quả hơn smartbind
.
Một thay thế với data.table
:
library(data.table)
df1 = data.frame(a = c(1:5), b = c(6:10))
df2 = data.frame(a = c(11:15), b = c(16:20), c = LETTERS[1:5])
rbindlist(list(df1, df2), fill = TRUE)
rbind
cũng sẽ làm việc trong data.table
miễn là các đối tượng được chuyển đổi thành data.table
đối tượng, vì vậy
rbind(setDT(df1), setDT(df2), fill=TRUE)
cũng sẽ làm việc trong tình huống này . Điều này có thể thích hợp hơn khi bạn có một vài data.tables và không muốn xây dựng một danh sách.
Tôi hiểu câu hỏi như:
a = data.frame(
x = c(1,2,3),
y = c(5,2,3)
)
b = data.frame(
u = c(6,2,3),
v = c(19,13,12)
)
dd=cbind(a, b)
str(dd)
'data.frame': 3 obs. of 4 variables:
$ x: num 1 2 3
$ y: num 5 2 3
$ u: num 6 2 3
$ v: num 19 13 12
Thật không may, sự hiểu biết của bạn có vẻ sai khi có thể được nhìn thấy bằng cách đọc câu trả lời được chấp nhận. Câu hỏi đặt ra là * liên kết hàng * hai dữ liệu.frames trong trường hợp chúng không có cùng một tập hợp các cột.Bài đăng của bạn thỏa thuận với * cột * ràng buộc bằng cách sử dụng 'cbind()'. Xin vui lòng, xem xét để sửa đổi bài viết của bạn với một câu trả lời duy nhất cho câu hỏi hoặc xóa nó. Cảm ơn bạn. – Uwe
Chỉ cần cho các tài liệu hướng dẫn.Bạn có thể thử các Stack
thư viện và chức năng của nó Stack
theo hình thức sau:
Stack(df_1, df_2)
Tôi cũng có ấn tượng rằng nó là nhanh hơn so với các phương pháp khác cho các tập dữ liệu lớn.
Hầu hết các câu trả lời cơ sở R giải quyết tình huống chỉ có một data.frame có các cột bổ sung hoặc data.frame kết quả sẽ có giao điểm của các cột. Kể từ khi OP viết Tôi hy vọng sẽ giữ lại các cột không khớp sau khi liên kết, một câu trả lời bằng cách sử dụng các phương thức R cơ bản để giải quyết vấn đề này có lẽ đáng để đăng.
Dưới đây, tôi trình bày hai phương pháp cơ sở R: Một phương pháp thay đổi dữ liệu ban đầu.frames và một cái không thay đổi. Ngoài ra, tôi cung cấp một phương thức tổng quát phương thức không phá hủy cho hơn hai data.frames.
Trước tiên, hãy lấy một số dữ liệu mẫu.
# sample data, variable c is in df1, variable d is in df2
df1 = data.frame(a=1:5, b=6:10, d=month.name[1:5])
df2 = data.frame(a=6:10, b=16:20, c = letters[8:12])
Hai data.frames, thay đổi bản gốc
Để giữ lại tất cả các cột từ cả hai data.frames trong một rbind
(và cho phép các chức năng để làm việc mà không dẫn đến một lỗi), bạn thêm cột NA vào mỗi data.frame với tên thiếu thích hợp được điền bằng cách sử dụng setdiff
.
# fill in non-overlapping columns with NAs
df1[setdiff(names(df2), names(df1))] <- NA
df2[setdiff(names(df1), names(df2))] <- NA
Bây giờ, rbind
-em
rbind(df1, df2)
a b d c
1 1 6 January <NA>
2 2 7 February <NA>
3 3 8 March <NA>
4 4 9 April <NA>
5 5 10 May <NA>
6 6 16 <NA> h
7 7 17 <NA> i
8 8 18 <NA> j
9 9 19 <NA> k
10 10 20 <NA> l
Lưu ý rằng hai dòng đầu tiên thay đổi data.frames gốc, df1 và df2, thêm các tập hợp đầy đủ các cột cho cả hai.
Hai data.frames, không làm thay đổi bản gốc
Để thoát khỏi data.frames gốc còn nguyên vẹn, vòng đầu tiên thông qua những cái tên mà khác nhau, trả lại một vector được đặt tên của NA đó được nối vào một danh sách với data.frame sử dụng c
. Sau đó, data.frame
chuyển đổi kết quả thành một dữ liệu thích hợp.bảng cho rbind
.
rbind(
data.frame(c(df1, sapply(setdiff(names(df2), names(df1)), function(x) NA))),
data.frame(c(df2, sapply(setdiff(names(df1), names(df2)), function(x) NA)))
)
Nhiều data.frames, không làm thay đổi bản gốc
Trong trường hợp mà bạn có nhiều hơn hai data.frames, bạn có thể làm những điều sau đây.
# put data.frames into list (dfs named df1, df2, df3, etc)
mydflist <- mget(ls(pattern="df\\d+")
# get all variable names
allNms <- unique(unlist(lapply(mydflist, names)))
# put em all together
do.call(rbind,
lapply(mydflist,
function(x) data.frame(c(x, sapply(setdiff(allNms, names(x)),
function(y) NA)))))
Có thể đẹp hơn một chút để không thấy tên hàng của dữ liệu gốc.frames? Sau đó làm điều này.
do.call(rbind,
c(lapply(mydflist,
function(x) data.frame(c(x, sapply(setdiff(allNms, names(x)),
function(y) NA)))),
make.row.names=FALSE))
- 1. kết hợp hai cấu trúc bảng giống nhau với các dữ liệu khác nhau
- 2. Đặt khung dữ liệu theo hai cột trong R
- 3. Sử dụng gấu trúc để chọn các hàng bằng cách sử dụng hai cột khác nhau từ khung dữ liệu?
- 4. Nhóm hàng khác nhau trong từng chuỗi kết hợp
- 5. Kết hợp hai khung dữ liệu và xóa các cột trùng lặp
- 6. Dán các cột của hai khung dữ liệu
- 7. Hợp nhất hai khung dữ liệu với nhau có cùng tên và kiểu dữ liệu biến
- 8. gấu trúc nhóm theo hai cột và nhân hai cột khác
- 9. Matching nhiều cột trên khung dữ liệu khác nhau và nhận được cột khác như kết quả
- 10. Làm cách nào để hợp nhất các khung dữ liệu theo tên hàng mà không thêm cột "Row.names"?
- 11. Kết hợp các cột từ các tập tin khác nhau
- 12. Tái một khung dữ liệu --- thay đổi hàng để cột
- 13. Chia nhỏ một khung dữ liệu theo số hàng
- 14. Lọc các khung dữ liệu một cột
- 15. Chuyển đổi tên hàng trong nhiều khung dữ liệu thành cột trong khung dữ liệu
- 16. hợp nhất các khung dữ liệu trong R
- 17. R: xóa các hàng khỏi một khung dữ liệu nằm trong một khung khác
- 18. Overplotting từ các khung dữ liệu khác nhau trong ggplot2
- 19. Cách trả lại một hàng từ nhóm theo nhiều cột
- 20. Đọc dữ liệu từ các cột/hàng Excel kết hợp bằng C#
- 21. Đặt khung dữ liệu dựa trên nội dung của một khung dữ liệu khác
- 22. Trừ giá trị của năm trước khỏi mỗi hàng được nhóm trong khung dữ liệu
- 23. Hợp nhất hai tệp trong linux với cột khác nhau
- 24. Áp dụng trên hai khung dữ liệu
- 25. Lọc khung dữ liệu theo giá trị trong cột
- 26. Đồng bộ hóa chiều rộng cột giữa các bảng trong hai khung khác nhau, v.v ..
- 27. R: làm thế nào để rbind hai khung dữ liệu khổng lồ mà không cần hết bộ nhớ
- 28. Liên kết hai bảng với số cột khác nhau
- 29. cách sắp xếp một khung dữ liệu theo 2 cột
- 30. Kết hợp các hàng và tổng giá trị của chúng
'rbind.fill' và' bind_rows() 'cả hai đều giảm âm thầm. – MERose
@MERose Hadley: "Có, tất cả các phương pháp dplyr đều bỏ qua các tên gọi." – zx8754