Rbindlist rbind की तुलना में "बेहतर" क्यों है?


135

मैं प्रलेखन के माध्यम से जा रहा हूं data.tableऔर एसओ पर यहां की कुछ वार्तालापों से भी देखा है जो इससे rbindlistबेहतर माना जाता है rbind

मैं जानना चाहूंगा कि क्यों rbindlistबेहतर है rbindऔर किन परिदृश्यों में rbindlistवास्तव में उत्कृष्टता है rbind?

क्या स्मृति उपयोग के मामले में कोई फायदा है?

जवाबों:


155

rbindlistका एक अनुकूलित संस्करण है do.call(rbind, list(...)), जिसका उपयोग करते समय धीमा होने के लिए जाना जाता हैrbind.data.frame


यह वास्तव में उत्कृष्टता कहां है

कुछ सवाल जो दिखाते हैं कि rbindlistचमक कहां है

पंक्ति द्वारा डेटा.फ्रेम की सूची का तेज़ वेक्टरकृत मर्ज

Do.call और ldply का उपयोग करके data.frame (~ 1 मिलियन) की लंबी सूची को एकल डेटा में परिवर्तित करने में परेशानी

ये बेंचमार्क हैं जो दिखाते हैं कि यह कितनी तेजी से हो सकता है।


rbind.data.frame एक कारण से धीमा है

rbind.data.frameबहुत सारी जाँच करता है, और नाम से मेल खाएगा। (यानी rbind.data.frame इस तथ्य के लिए जिम्मेदार होगा कि कॉलम अलग-अलग ऑर्डर में हो सकते हैं, और नाम से मेल खा सकते हैं), rbindlistइस तरह की जाँच नहीं करता है, और स्थिति से जुड़ जाएगा

जैसे

do.call(rbind, list(data.frame(a = 1:2, b = 2:3), data.frame(b = 1:2, a = 2:3)))
##    a b
## 1  1 2
## 2  2 3
## 3  2 1
## 4  3 2

rbindlist(list(data.frame(a = 1:5, b = 2:6), data.frame(b = 1:5, a = 2:6)))
##     a b
##  1: 1 2
##  2: 2 3
##  3: 1 2
##  4: 2 3

Rbindlist की कुछ अन्य सीमाएँ

यह तब से बग से निपटने के लिए संघर्ष करता था factors, जो तब से तय है:

rbindlist दो data.tables जहां एक कारक होता है और दूसरे में एक कॉलम के लिए वर्ण प्रकार होता है ( बग # 2650 )

इसमें डुप्लिकेट कॉलम नामों के साथ समस्याएं हैं

चेतावनी संदेश देखें : rbindlist (allargs) में: NA जबरदस्ती द्वारा शुरू किया गया: data.table में संभव बग? ( बग # 2384 )


rbind.data.frame rownames निराशा हो सकती है

rbindlistसंभाल कर सकते हैं lists data.framesऔर data.tables, और rownames के बिना एक data.table वापस आ जाएगी

आप उपद्रवियों के एक दल में do.call(rbind, list(...)) देख पाने का उपयोग कर सकते हैं

Do.call के अंदर rbind का उपयोग करते समय पंक्तियों का नाम बदलने से कैसे बचें?


मेमोरी क्षमता

स्मृति के संदर्भ में rbindlistकार्यान्वित किया जाता है C, इसलिए स्मृति कुशल है, यह setattrसंदर्भ द्वारा विशेषताओं को सेट करने के लिए उपयोग करता है

rbind.data.frameमें कार्यान्वित किया जाता Rहै, यह बताए के बहुत सारे, और का उपयोग करता है करता है attr<-(और class<-और rownames<-होगा (आंतरिक) बनाया data.frame की प्रतिलिपियां भी बना जो सभी के।


1
FYI करें attr<-, class<-और (मुझे लगता है) rownames<-सभी जगह संशोधित होते हैं।
हैडली

5
@ क्या आप सुनिश्चित हैं? कोशिश करो DF = data.frame(a=1:3); .Internal(inspect(DF)); tracemem(DF); attr(DF,"test") <- "hello"; .Internal(inspect(DF))
मैट डॉवले

4
rbind.data.frameविशेष "अपहरण" तर्क है - जब इसका पहला तर्क ए है data.table, तो .rbind.data.tableइसके बजाय कॉल करता है, जो थोड़ी जांच करता है और फिर rbindlistआंतरिक रूप से कॉल करता है। इसलिए यदि आपके पास पहले से ही data.tableवस्तुओं को बांधने के लिए है, तो शायद rbindऔर बीच में बहुत कम प्रदर्शन अंतर है rbindlist
केन विलियम्स

6
मेल, इस पोस्ट को शायद संपादन की आवश्यकता है, अब यह rbindlistनाम ( use.names=TRUE) से मेल खाने में सक्षम है और लापता कॉलम ( fill=TRUE) भी भर सकता है । मैं नवीनीकृत किया है इस , यह और इस पद। क्या आप इसे संपादित करते हैं या यह ठीक है कि क्या मैं इसे करता हूं? किसी भी तरह मेरे द्वारा ठीक है।
अरुण

1
dplyr::rbind_listयह भी इसी तरह की है
हैडल

48

द्वारा v1.9.2, rbindlistकाफी विकसित हुआ था, जिसमें कई विशेषताएं शामिल हैं:

  • SEXPTYPEबाइंडिंग करते समय सबसे अधिक कॉलम चुनना - FR # 2456 और बग # 4981 को v1.9.2बंद करने में लागू किया गया ।
  • factorस्तंभों को ठीक से संभालना - सबसे पहले बग # 2650 को v1.8.10बंद करने में लागू किया गया और बाध्यकारी आदेशों को ध्यान में रखते हुए एफआर # 4856 और बग # 5019 को बंद कर दिया गयाv1.9.2

इसके अलावा, में v1.9.2, rbind.data.tableएक fillतर्क भी प्राप्त हुआ , जो कि आर में लागू होने वाले लापता कॉलमों को भरकर बांधने की अनुमति देता है।

अब v1.9.3, इन मौजूदा सुविधाओं पर और भी अधिक सुधार हुए हैं:

  • rbindlistएक तर्क प्राप्त करता है use.names, जो डिफ़ॉल्ट रूप से FALSEपश्चगामी संगतता के लिए है।
  • rbindlistएक तर्क भी प्राप्त करता है fill, जो डिफ़ॉल्ट रूप से भी FALSEपश्चगामी संगतता के लिए है।
  • इन विशेषताओं को C में लागू किया गया है, और कार्यक्षमता को जोड़ते हुए गति में समझौता नहीं करने के लिए सावधानीपूर्वक लिखा गया है।
  • चूंकि rbindlistअब नामों से मेल कर सकते हैं और लापता कॉलम भर सकते हैं, rbind.data.tableबस rbindlistअब कॉल करें । एकमात्र अंतर यह है कि use.names=TRUEडिफ़ॉल्ट रूप से rbind.data.table, पश्चगामी संगतता के लिए।

rbind.data.frameज्यादातर प्रतियां (जो @mnel के रूप में अच्छी तरह से बाहर इंगित करता है) के कारण काफी धीमा हो जाता है जिसे टाला जा सकता है (सी में स्थानांतरित करके)। मुझे लगता है कि यह एकमात्र कारण नहीं है। स्तंभ के नामों की जाँच / मिलान के लिए कार्यान्वयन rbind.data.frameतब भी धीमा हो सकता है, जब प्रति डेटा कई स्तंभ हों। बाइंड करने के लिए ऐसे कई डेटा हैं।

हालाँकि, उस rbindlistकमी (एड) में कुछ विशेषताएं (जैसे कारक स्तरों की जाँच करना या नाम मिलान करना) बहुत छोटे (या नहीं) वजन की तुलना में तेज़ होती हैं rbind.data.frame। यह इसलिए है क्योंकि वे सी में सावधानी से लागू किए गए थे, गति और स्मृति के लिए अनुकूलित।

यहाँ एक बेंचमार्क है कि प्रकाश डाला कुशल अच्छी तरह का उपयोग कर के रूप में स्तंभ नाम से मिलान करते हुए बंधन है rbindlistकी use.namesसे सुविधा v1.9.3। डेटा सेट में 10000 data.frames होते हैं, जिनमें से प्रत्येक का आकार 10 * 500 होता है।

ध्यान दें: इस मानदंड में एक तुलना शामिल करने के लिए अद्यतन किया गया है dplyrकीbind_rows

library(data.table) # 1.11.5, 2018-06-02 00:09:06 UTC
library(dplyr) # 0.7.5.9000, 2018-06-12 01:41:40 UTC
set.seed(1L)
names = paste0("V", 1:500)
cols = 500L
foo <- function() {
    data = as.data.frame(setDT(lapply(1:cols, function(x) sample(10))))
    setnames(data, sample(names))
}
n = 10e3L
ll = vector("list", n)
for (i in 1:n) {
    .Call("Csetlistelt", ll, i, foo())
}

system.time(ans1 <- rbindlist(ll))
#  user  system elapsed 
# 1.226   0.070   1.296 

system.time(ans2 <- rbindlist(ll, use.names=TRUE))
#  user  system elapsed 
# 2.635   0.129   2.772 

system.time(ans3 <- do.call("rbind", ll))
#   user  system elapsed 
# 36.932   1.628  38.594 

system.time(ans4 <- bind_rows(ll))
#   user  system elapsed 
# 48.754   0.384  49.224 

identical(ans2, setDT(ans3)) 
# [1] TRUE
identical(ans2, setDT(ans4))
# [1] TRUE

नामों के लिए जाँच किए बिना स्तंभों को बांधना सिर्फ 1.3 लिया जहाँ स्तंभ नामों की जाँच करना और उचित रूप से बाँधना केवल 1.5 सेकंड अधिक लिया गया। बेस सॉल्यूशन की तुलना में, यह 14x तेज़ है, और 18x तेज़ है dplyr

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.