উত্তর:
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 মিনিটের পরে এটিকে বাতিল করে দিয়েছি ।
যদি ডিএফ 1- এর কলামগুলি ডিএফ 2 (কলামের নাম অনুসারে) এর একটি উপসেট হয়:
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
so
rbind(setDT(df1), setDT(df2), fill=TRUE)
এই পরিস্থিতিতে কাজ করবে। আপনি যখন বেশ কয়েকটি ডেটা টেবিল রাখেন এবং একটি তালিকা তৈরি করতে চান না তখন এটি পছন্দনীয় হতে পারে।
intersect
পদ্ধতির মতো অন্যান্য উত্তরগুলি কেবল 2 ডেটা ফ্রেমের জন্য কাজ করে এবং সহজেই সাধারণীকরণ হয় না।
বেস আর এর বেশিরভাগ উত্তরগুলির মধ্যে পরিস্থিতি সম্বোধন করা হয় যেখানে কেবলমাত্র একটি ডেটা.ফ্রেমে অতিরিক্ত কলাম রয়েছে বা ফলস্বরূপ ডেটা.ফ্রেমে কলামগুলির ছেদ থাকবে। যেহেতু ওপি লিখেছেন আমি কলামগুলি বাঁধার পরেও মেলে না তা ধরে রাখার প্রত্যাশা করছি , এই সমস্যাটির সমাধানের জন্য বেস আর পদ্ধতির সাহায্যে একটি উত্তর সম্ভবত পোস্ট করার উপযুক্ত।
নীচে, আমি দুটি বেস আর পদ্ধতি উপস্থাপন করছি: একটি যা মূল ডেটা ফ্রেমগুলিকে পরিবর্তন করে এবং একটি যা তা নয়। অতিরিক্তভাবে, আমি এমন একটি পদ্ধতি অফার করি যা অ-ধ্বংসাত্মক পদ্ধতিটিকে দুটিরও বেশি ডেটা.ফ্রেমে সাধারণ করে তোলে।
প্রথমে আসুন কিছু নমুনা ডেটা নেওয়া যাক।
# 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
(এবং কোনও ত্রুটির ফলশ্রুতি ছাড়াই ফাংশনটি কাজ করার অনুমতি দিন), আপনি প্রতিটি ডেটাতে এনএ কলাম যুক্ত করবেন in ব্যবহার 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
নোট করুন যে প্রথম দুটি লাইন দু'এই কলামের পুরো সেট যুক্ত করে মূল তথ্য.ফ্রেমেস, ডিএফ 1 এবং ডিএফ 2 কে পরিবর্তন করে।
দুটি ডাটা.ফ্রেমে, আসল পরিবর্তন করবেন না
আসল ডাটা.ফ্রেমগুলি অক্ষত রেখে প্রথমে পৃথক নামের মাধ্যমে লুপ করুন, এন.এ. এর একটি নামযুক্ত ভেক্টরকে ডেটা.ফ্রেম ব্যবহার করে একটি তালিকায় সংযুক্ত করে ফিরিয়ে দিন 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)))
)
অনেক ডেটা.ফ্রেমেস, অরিজিনালগুলিতে পরিবর্তন করবেন না
যে আপনার কাছে দুটিরও বেশি ডেটা রয়েছে ra ফ্রেমগুলি, আপনি নিম্নলিখিতটি করতে পারেন।
# 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)))))
আসল ডেটা.ফ্রেমসের সারি নামগুলি না দেখতে কিছুটা ভাল লাগবে? তাহলে এই কাজ।
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])
আমি এটি করার জন্য একটি ফাংশন লিখেছিলাম কারণ আমার কোডটি পছন্দ করে যদি কিছু ভুল হয় তবে আমাকে জানাতে। এই ফাংশনটি আপনাকে স্পষ্ট করে বলবে কোন কলামের নাম মেলে না এবং যদি আপনার কোনওরকম মিল নেই। তারপরে এটি যাইহোক ডেটা.ফ্রেমগুলি একত্রিত করার জন্য যথাসাধ্য চেষ্টা করবে। সীমাবদ্ধতাটি হ'ল আপনি একবারে কেবল দুটি ডেটা ফ্রেমগুলি একত্রিত করতে পারেন।
### 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)
}
হতে পারে আমি আপনার প্রশ্নটি সম্পূর্ণরূপে ভুলভাবে লিখেছি, তবে "আমি আশা করি যে কলামগুলি বাঁধার পরেও মেলে না তা ধরে রাখতে" আমাকে মনে করে যে আপনি কোনও এসকিউএল কোয়েরির সাথে সন্ধান করছেন left join
বা সন্ধান করছেন right join
। আর-এর merge
ফাংশন রয়েছে যা আপনাকে বাম, ডান, বা অভ্যন্তরীণ এসকিউএল-এ টেবিলগুলিতে যোগদানের অনুরূপ নির্দিষ্ট করতে দেয়।
এখানে ইতিমধ্যে এখানে এই বিষয়ে একটি দুর্দান্ত প্রশ্নোত্তর রয়েছে: ডেটা ফ্রেমগুলিতে (অভ্যন্তরীণ, বাহ্যিক, বাম, ডান) কীভাবে যোগদান করতে হবে?
গেটলস / স্মার্টবাইন্ড তারিখগুলির সাথে কাজ করা পছন্দ করেনি, সম্ভবত এটি কারণ ছিল ওয়েভচারিং। সুতরাং এখানে আমার সমাধান ...
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()
-Function, মান লেবেল সহ ফ্রিকোয়েন্সি টেবিল ছাপে যদি ডাটা লেবেল করা হয়েছে।
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()
উভয় নিঃশব্দে rownames ড্রপ।