是否可以對兩個不具有相同列的數據框進行行綁定?我希望保留綁定後不匹配的列。當它們有不同的列集合時,按行(rbind)組合兩個數據幀
回答
rbind.fill
從包裝plyr
可能是你在找什麼。
您可以使用gtools
包中的smartbind
。
例子:
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
我試着用兩個大數據幀(總共大約3 * 10^6行)'smartbind'並在10分鐘後中止。 – Joe 2017-05-11 11:39:02
你也可以只退出共同列名。
> cols <- intersect(colnames(df1), colnames(df2))
> rbind(df1[,cols], df2[,cols])
如果DF1列是那些在DF2一個子集(按列名):
df3 <- rbind(df1, df2[, names(df1)])
也許我完全誤解了你的問題,但「我希望能保留列綁定後不匹配「使我認爲您正在尋找類似於SQL查詢的left join
或right join
。 R的merge
函數允許您指定左連接,右連接或內連接,類似於SQL中的連接表。
已經有關於這一主題在這裏一個很大的問題和答案:How to join (merge) data frames (inner, outer, left, right)?
我寫了一個功能,因爲我喜歡我的代碼,告訴我什麼是錯的做到這一點。此函數將明確告訴您哪些列名稱不匹配,以及是否有類型不匹配。然後,它會盡最大努力組合數據框架。限制是您一次只能組合兩個數據幀。
### 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/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)
}
最近的一個解決方案是使用dplyr
的bind_rows
功能,我認爲比smartbind
更有效。
與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
也將在data.table
工作,只要該對象轉換爲data.table
對象,所以
rbind(setDT(df1), setDT(df2), fill=TRUE)
也將在這種情況下,工作。當你有幾個data.tables並且不想構造一個列表時,這可能會更好。
我明白的問題爲:
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
不幸的是,通過閱讀接受的答案可以看出您的理解錯誤。問題是關於*行綁定*兩個data.frames,以防它們沒有相同的一組列。您的文章使用'cbind()'處理* column *綁定。請考慮修改您的帖子,並將其刪除。謝謝。 – Uwe 2017-08-07 04:57:16
只是爲了文檔。您可以嘗試Stack
庫及其下面的表格功能Stack
:
Stack(df_1, df_2)
我也有印象,它比其他方法大數據集的速度更快。
大多數基準R答案解決了只有一個數據幀具有附加列或結果數據幀具有列交集的情況。由於OP寫道我希望保留綁定後不匹配的列,使用基本R方法解決此問題的答案可能值得發佈。
下面我介紹兩種基本的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所有列在rbind
(並允許功能,而不會產生錯誤的工作),你將NA列添加到每個data.frame中,並使用setdiff
填寫相應的缺失名稱。
# 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)
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
注意,前兩行改變原始data.frames,DF1和DF2,加上全套到兩列的。
兩個data.frames,不改變原件
要離開了原來的data.frames通過不同的名字不變,第一次循環,返回連接成一個列表的NAS命名矢量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,不改變原件
在你有兩個以上的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))
- 1. 合併具有幾個不同列的兩個數據幀
- 2. 使用rbind()組合不同的數據集
- 3. 合併具有不同行數的兩個數據幀兩列名稱
- 4. 合併具有不同行數和不同列的數據幀
- 5. 當在R中組合兩個數據幀時合併跳過隨機行
- 6. 如何將兩個數據幀按相同元素組合
- 7. 包括間隙合併的數據幀時具有rbind
- 8. 排序兩個組合的數據幀
- 9. 如何組合兩個不同長度的數據幀?
- 10. 在Pandas中合併/組合兩個具有不同頻率時間序列索引的數據幀?
- 11. 評估來自兩個數據幀的行的所有組合
- 12. 合併兩個數據幀的列
- 13. Rbind /追加兩個列表,其中包含具有相同列但行數不同的數據幀
- 14. 聯合使用不同列的兩個火花數據幀
- 15. 組合數據幀的行
- 16. 基於兩列組合的子集數據幀
- 17. 組合不同長度的數據幀
- 18. 組合兩個數據幀,並顯示它們的區別 - Python的熊貓
- 19. 檢查兩個數據幀是否具有相同的行集合
- 20. Mysql結合兩個結果,並按字段將它們組合
- 21. 按鍵列合併數據幀行
- 22. 從不同的數據合併列幀
- 23. 合併兩個數據幀
- 24. 合併兩個數據幀
- 25. 結合兩個數據幀的列表,dataframe的數據幀
- 26. 基於列合併兩個數據幀
- 27. 按不同列名合併多個列的SAS數據集
- 28. 在SAS SQL中合併兩列數據集,列略有不同
- 29. 具有不同數目的行合併兩個數據幀中的R
- 30. 按多列數值組合數據集
'rbind.fill'和'bind_rows()'都默默地放棄了rownames。 – MERose 2017-12-05 16:40:30
@Merose Hadley:「是的,所有的dplyr方法都會忽略rownames。」 – zx8754 2017-12-07 09:11:05