当两行数据帧(rbind)有不同的列组合时,组合两个数据帧

是否有可能绑定两个没有相同的列的数据框? 我希望保留绑定后不匹配的列。

从包装plyr可能是你在找什么。

最近的解决方案是使用dplyrbind_rows函数,我认为它比smartbind更高效。

您可以使用gtools包中的gtools

例:

 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 abc 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 

如果df1中的列是df2中的列的子集(按列名称):

 df3 <- rbind(df1, df2[,names(df1)] 

data.table的替代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) 

只要将对象转换为data.table对象, rbind也将在data.table工作

 rbind(setDT(df1), setDT(df2), fill=TRUE) 

也会在这种情况下工作。 当你有几个data.tables并且不想构建一个列表时,这可能会更好。

你也可以把普通的列名拖出来。

 > cols <- intersect(colnames(df1), colnames(df2)) > rbind(df1[,cols], df2[,cols]) 

我写了一个函数来做到这一点,因为我喜欢我的代码告诉我是否有错误。 这个函数会明确地告诉你哪个列名不匹配,以及是否有类型不匹配。 那么它将尽最大努力来结合data.frames。 限制是您一次只能组合两个数据帧。

 ### 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)) { la <- all.names[i]%in%a.names pos.a <- match(all.names[i],a.names) typ.a <- a.type[pos.a] lb <- all.names[i]%in%b.names pos.b <- match(all.names[i],b.names) typ.b <- b.type[pos.b] if(la & lb) { 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 (la) { 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) } 

也许我完全误解了你的问题,但是“我希望保留绑定后不匹配的列”让我觉得你正在寻找类似于SQL查询的left joinright join 。 R具有merge功能,可以让您指定类似于SQL中的连接表的左连接,右连接或内连接。

这里已经有了一个很好的问题和答案: 如何连接(合并)数据框架(内部,外部,左,右)?

只是为了文件。 您可以按以下形式尝试Stack库及其功能Stack

 Stack(df_1, df_2) 

我也有这样的印象,它比其他大型数据集的方法更快。

gtools / smartbind不喜欢与日期工作,可能是因为它是as.vectoring。 所以这是我的解决方案…

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

大多数基准R问题都是针对只有一个数据帧具有附加列或结果数据帧具有列的交集的情况。 由于OP写入我希望保留绑定后不匹配的列,使用基本R方法的帖子可能值得张贴。

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

两个data.frames,改变原件
为了保留两个data.frames中的所有列,可以用下面的三行来完成。

 # fill in non-overlapping columns with NAs df1[setdiff(names(df2), names(df1))] <- NA df2[setdiff(names(df1), names(df2))] <- NA 

现在, rbind -em

 rbind(df1, df2) abdc 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 

请注意,前两行更改了原始data.frames,df1和df2,将全部列添加到两者。


两个data.frames,不要改变原件
一种方法返回上面的data.frame,而原封不动的是循环通过不同的名称,返回一个名为NA的向量,它们与data.frame使用c连接成一个列表。 然后, data.frame将结果转换为rbind的适当data.frame。

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

许多数据框架,不会改变原件
在你有两个以上的data.frames的情况下,你可以做到以下几点。

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

也许有点更好,看不到原始data.frames的行名称? 然后做这个。

 do.call(rbind, c(lapply(mydflist, function(x) data.frame(c(x, sapply(setdiff(allNms, names(x)), function(y) NA)))), make.row.names=FALSE)) 
 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)])) } 

我把这个问题理解为:

 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