जवाबों:
rbind.fill
पैकेज से वह plyr
हो सकता है जिसे आप ढूंढ रहे हैं।
एक अधिक हाल के समाधान का उपयोग करने के लिए है dplyr
के bind_rows
समारोह जो मुझे लगता है की तुलना में अधिक कुशल है smartbind
।
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])
dplyr::bind_rows(df1, df2)
a b c
1 1 6 <NA>
2 2 7 <NA>
3 3 8 <NA>
4 4 9 <NA>
5 5 10 <NA>
6 11 16 A
7 12 17 B
8 13 18 C
9 14 19 D
10 15 20 E
ABC
को वर्ण से संख्यात्मक में नहीं बदला जा सकता है। क्या पहले कॉलम को बदलने का कोई तरीका है?
आप पैकेज smartbind
से उपयोग कर सकते हैं 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
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
smartbind
दो बड़े डेटा फ़्रेमों के साथ (कुल मिलाकर लगभग 3 * 10 ^ 6 पंक्तियों में) की कोशिश की और 10 मिनट के बाद इसे निरस्त कर दिया।
में स्तंभों तो DF1 में उन लोगों के एक सबसेट है df2 (स्तंभ नाम से):
df3 <- rbind(df1, df2[, names(df1)])
इसके साथ एक विकल्प 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 की एक जोड़ी हो और सूची का निर्माण न करना हो।
intersect
दृष्टिकोण की तरह , केवल 2 डेटाफ्रेम के लिए काम करते हैं और आसानी से सामान्य नहीं करते हैं।
अधिकांश बेस R उत्तर उस स्थिति को संबोधित करते हैं जहां केवल एक data.frame के पास अतिरिक्त कॉलम हैं या जिसके परिणामस्वरूप data.frame स्तंभों का प्रतिच्छेदन होगा। चूंकि ओपी लिखते हैं, मैं उन स्तंभों को बनाए रखने की उम्मीद कर रहा हूं जो बांधने के बाद मेल नहीं खाते हैं , इस मुद्दे को संबोधित करने के लिए आधार आर विधियों का उपयोग कर एक उत्तर संभवतः पोस्ट करने के लायक है।
नीचे, मैं दो आधार आर तरीके प्रस्तुत करता हूं: एक जो मूल data.frames को बदल देता है, और एक जो नहीं करता है। इसके अतिरिक्त, मैं एक ऐसी विधि प्रदान करता हूं जो गैर-विनाशकारी विधि को दो से अधिक डेटा.फ्रेम में सामान्यीकृत करती है।
पहले, चलो कुछ नमूना डेटा प्राप्त करते हैं।
# 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])
दो डेटा.फ्रेम, ऑरिजनल में परिवर्तन
। दोनों डेटा rbind
( एफ़ में और बिना किसी त्रुटि के परिणाम के बिना फ़ंक्शन को काम करने की अनुमति देने के लिए) सभी कॉलम बनाए रखने के लिए , आप प्रत्येक डेटा में एनए कॉलम जोड़ें। उपयुक्त अनुपलब्ध नामों के साथ फ़्रेम करें का उपयोग कर setdiff
।
# fill in non-overlapping columns with NAs
df1[setdiff(names(df2), names(df1))] <- NA
df2[setdiff(names(df1), names(df2))] <- NA
अब, rbind
-म
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 को बदल देती हैं, दोनों स्तंभों का पूरा सेट जोड़ देती हैं।
दो डेटा.फ्रेम, मूल परिवर्तन न
करें। मूल डेटा को छोड़ दें। अलग-अलग, नामों के माध्यम से पहले लूप को अलग करें, NA का एक नामांकित वेक्टर लौटाएं जिसे डेटा के साथ एक सूची में संक्षिप्त किया गया है c
। फिर, data.frame
परिणाम को एक उपयुक्त डेटा में बदल देता है 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)))
)
कई 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))
mydflist <- list(as, dr, kr, hyt, ed1, of)
। यह एक सूची ऑब्जेक्ट का निर्माण करना चाहिए जो आपके पर्यावरण के आकार को नहीं बढ़ाता है, लेकिन सूची के प्रत्येक तत्व को इंगित करता है (जब तक आप बाद में किसी भी सामग्री को नहीं बदलते)। ऑपरेशन के बाद, सूची ऑब्जेक्ट को हटा दें, बस सुरक्षित होने के लिए।
आप सामान्य कॉलम नामों को भी निकाल सकते हैं।
> 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)) {
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)
}
हो सकता है कि मैंने आपके प्रश्न को पूरी तरह से गलत कर दिया हो, लेकिन "मैं उन स्तंभों को बनाए रखने की उम्मीद कर रहा हूं जो बाइंड के बाद मेल नहीं खाते हैं" मुझे लगता है कि आप SQL क्वेरी के समान left join
या इसके right join
समान देख रहे हैं । R में merge
फ़ंक्शन है जो आपको बाएं, दाएं, या आंतरिक को SQL में टेबल से जुड़ने के समान निर्दिष्ट करता है।
इस विषय पर पहले से ही एक महान प्रश्न और उत्तर यहां दिया गया है: डेटा फ़्रेम (आंतरिक, बाहरी, बाएं, दाएं) कैसे जुड़ें (मर्ज करें)?
gtools / smartbind Dates के साथ काम करना पसंद नहीं था, शायद इसलिए कि यह 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)
}
सिर्फ दस्तावेज के लिए। आप Stack
पुस्तकालय और उसके कार्य Stack
को निम्न रूप में आज़मा सकते हैं :
Stack(df_1, df_2)
मुझे यह भी आभास होता है कि यह बड़े डेटा सेट के लिए अन्य विधियों की तुलना में तेज़ है।
आप उपयोग भी कर सकते हैं sjmisc::add_rows()
, जो उपयोग करता है dplyr::bind_rows()
, लेकिन इसके विपरीत bind_rows()
, add_rows()
विशेषताओं को संरक्षित करता है और इसलिए लेबल किए गए डेटा के लिए उपयोगी है ।
एक लेबल किए गए डेटासेट के साथ निम्न उदाहरण देखें। frq()
समारोह, मूल्य लेबल के साथ आवृत्ति तालिकाओं प्रिंट अगर डेटा लेबल किया गया है।
library(sjmisc)
library(dplyr)
data(efc)
# select two subsets, with some identical and else different columns
x1 <- efc %>% select(1:5) %>% slice(1:10)
x2 <- efc %>% select(3:7) %>% slice(11:20)
str(x1)
#> 'data.frame': 10 obs. of 5 variables:
#> $ c12hour : num 16 148 70 168 168 16 161 110 28 40
#> ..- attr(*, "label")= chr "average number of hours of care per week"
#> $ e15relat: num 2 2 1 1 2 2 1 4 2 2
#> ..- attr(*, "label")= chr "relationship to elder"
#> ..- attr(*, "labels")= Named num 1 2 3 4 5 6 7 8
#> .. ..- attr(*, "names")= chr "spouse/partner" "child" "sibling" "daughter or son -in-law" ...
#> $ e16sex : num 2 2 2 2 2 2 1 2 2 2
#> ..- attr(*, "label")= chr "elder's gender"
#> ..- attr(*, "labels")= Named num 1 2
#> .. ..- attr(*, "names")= chr "male" "female"
#> $ e17age : num 83 88 82 67 84 85 74 87 79 83
#> ..- attr(*, "label")= chr "elder' age"
#> $ e42dep : num 3 3 3 4 4 4 4 4 4 4
#> ..- attr(*, "label")= chr "elder's dependency"
#> ..- attr(*, "labels")= Named num 1 2 3 4
#> .. ..- attr(*, "names")= chr "independent" "slightly dependent" "moderately dependent" "severely dependent"
bind_rows(x1, x1) %>% frq(e42dep)
#>
#> # e42dep <numeric>
#> # total N=20 valid N=20 mean=3.70 sd=0.47
#>
#> val frq raw.prc valid.prc cum.prc
#> 3 6 30 30 30
#> 4 14 70 70 100
#> <NA> 0 0 NA NA
add_rows(x1, x1) %>% frq(e42dep)
#>
#> # elder's dependency (e42dep) <numeric>
#> # total N=20 valid N=20 mean=3.70 sd=0.47
#>
#> val label frq raw.prc valid.prc cum.prc
#> 1 independent 0 0 0 0
#> 2 slightly dependent 0 0 0 0
#> 3 moderately dependent 6 30 30 30
#> 4 severely dependent 14 70 70 100
#> NA NA 0 0 NA NA
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)]))
}
rbind.fill
औरbind_rows()
दोनों चुपचाप रोने वालों को छोड़ देते हैं।