2015-06-03 7 views
10

मैंने देखा है कि cbind डेटा.tables के लिए rbind से काफी लंबा समय लेता है। इसका कारण क्या है?cbind बनाम rbind data.table

> dt <- as.data.table(mtcars)        
> new.dt <- copy(dt)          
> timeit({for (i in 1:100) dt.new <- rbind(dt.new, dt)}) 
    user system elapsed         
    0.237 0.012 0.253         
> new.dt <- copy(dt)          
> timeit({for (i in 1:100) dt.new <- cbind(dt.new, dt)}) 
    user system elapsed         
14.795 0.090 14.912  

कहाँ

timeit <- function(expr) 
{ 
    ptm <- proc.time() 
    expr 
    proc.time() - ptm 
} 
+0

मैं data.table के आंतरिक पता नहीं है, लेकिन मैं नए रिकॉर्ड (पंक्तियाँ) जोड़ने लगता है कि आसान है:

आप नीचे देख सकते हैं, cbind के लिए बुनियादी संचालन ज्यादा rbind तुलना में तेजी से कर रहे हैं नए चर (कॉलम) के साथ तालिका पुनर्गठन की तुलना में। – zx8754

+0

@ zx8754 हां मैं भी अपने संदेह से सहमत हूं, उत्सुक है कि विशिष्ट बोतल गर्दन क्या है। हो सकता है कि यह स्मृति आवंटन हो, शायद अधिक मेमोरी आवश्यकताएं, उम्मीद है कि पैकेज की नीची किरदार के साथ कोई familar प्रकाश डाल सकता है .. – andrew

+3

जब तक मैं गलत नहीं हूं, 'data.table' पर 'rbind' को कॉल करना' rbind.data प्रेषित करेगा। तालिका', जो 'data.table' फ़ंक्शन 'rbindlist'- को सी में लागू किया गया है, और बहुत तेज़ है। @ अरुण का जवाब देखें [यहां] (http://stackoverflow.com/questions/15673550/why-is-rbindlist-better-than-rbind)। इसके शीर्ष पर, कॉलम-वार संशोधनों और पंक्ति-वार संशोधनों (स्मृति में वस्तुओं को कैसे संग्रहीत किया जाता है) के बीच लगभग निश्चित रूप से मौलिक अंतर होते हैं, इसलिए यह वास्तव में "सेब-टू-सेब" तुलना नहीं है। सबसे अधिक संभावना है कि 'data.table' कॉलम को कुशलतापूर्वक संशोधित करने के लिए': = 'लागू करता है। – nrussell

उत्तर

8

अंत में मैं इस alloc.col करने के लिए नीचे धीमी गति से किया जा रहा है एक पाश जहां यह स्तंभों से विभिन्न विशेषताओं को हटा के कारण आता है लगता है। मुझे पूरा यकीन नहीं है कि ऐसा क्यों हुआ, शायद अरुण या मैट समझा सकते हैं।

cbind.dt.simple = function(...) { 
    x = c(...) 
    setattr(x, "class", c("data.table", "data.frame")) 
    ans = .Call(data.table:::Calloccolwrapper, x, max(100L, ncol(x) + 64L), FALSE) 
    .Call(data.table:::Csetnamed, ans, 0L) 
} 

library(microbenchmark) 

microbenchmark(rbind(dt, dt), cbind(dt, dt), cbind.dt.simple(dt, dt)) 
#Unit: microseconds 
#     expr  min  lq  mean median  uq  max neval 
#   rbind(dt, dt) 785.318 996.5045 1665.1762 1234.4045 1520.3830 21327.426 100 
#   cbind(dt, dt) 2350.275 3022.5685 3885.0014 3533.7595 4093.1975 21606.895 100 
# cbind.dt.simple(dt, dt) 74.125 116.5290 168.5101 141.9055 180.3035 1903.526 100 
+0

मुझे लगता है कि 'cbind2 <- function (...) (setattr (do.call (c, list (...)), "class", c ("data.table", "data.frame"))) 'भी तेज है। मैं वास्तव में 'सी * 'कार्यों के साथ क्या हो रहा है उसका पालन नहीं करता, इसलिए शायद मुझे कुछ याद आ रहा है। 'all.equal (cbind.dt.simple (डीटी, डीटी), cbind2 (डीटी, डीटी)) # TRUE' – Frank

+0

@ फ्रैंक सही है, लेकिन इससे कुछ चीजें अपूर्ण होती हैं, उदाहरण दें 'cbind2 (डीटी, डीटी) [, न्यूकॉल: = 5]' – eddi

+0

आह, मैं देखता हूं। मेरा अगला विचार 'setDT (setattr (do.call (सी, सूची (...)), "वर्ग", सी ("डेटा.फ्रेम")))' रास्ता धीमा था। ओह, बस 'setDT (do.call (सी, सूची (...)))' काम करता है, लेकिन वही (धीमी) गति है। – Frank