2011-03-09 16 views
7

मेरे पास 2 मिलियन पंक्तियों और 15 कॉलम के साथ डेटा फ्रेम है। मैं इन कॉलमों में से 3 से ddply के साथ समूह करना चाहता हूं (सभी 3 कारक हैं, और इन कारकों के 780,000 अद्वितीय संयोजन हैं), और 3 कॉलम का भारित माध्य प्राप्त करें (मेरे डेटा सेट द्वारा परिभाषित वजन के साथ)। निम्नलिखित यथोचित जल्दी है:सारांश और ddply कैसे तेजी से गति?

system.time(a2 <- aggregate(cbind(col1,col2,col3) ~ fac1 + fac2 + fac3, data=aggdf, FUN=mean)) 
    user system elapsed 
91.358 4.747 115.727 

समस्या यह है कि मैं मतलब के बजाय weighted.mean उपयोग करने के लिए मेरी कुल कॉलम गणना करना चाहते हैं।

अगर मैं कोशिश एक ही डेटा फ्रेम (ध्यान दें, मैं अपरिवर्तनीय करने के लिए डाली), निम्नलिखित 20 मिनट के बाद खत्म नहीं करता है पर ddply निम्नलिखित:

x <- ddply(idata.frame(aggdf), 
     c("fac1","fac2","fac3"), 
     summarise, 
     w=sum(w), 
     col1=weighted.mean(col1, w), 
     col2=weighted.mean(col2, w), 
     col3=weighted.mean(col3, w)) 

इस आपरेशन सीपीयू भूख लगती है, लेकिन नहीं बहुत रैम-गहन।

संपादित करें: तो मैंने इस छोटे से काम को लिखना समाप्त कर दिया, जो भारित माध्य के कुछ गुणों का लाभ उठाकर थोड़ा "धोखा देती है" और स्लाइस के बजाए पूरे वस्तु पर एक गुणा और विभाजन करता है।

weighted_mean_cols <- function(df, bycols, aggcols, weightcol) { 
    df[,aggcols] <- df[,aggcols]*df[,weightcol] 
    df <- aggregate(df[,c(weightcol, aggcols)], by=as.list(df[,bycols]), sum) 
    df[,aggcols] <- df[,aggcols]/df[,weightcol] 
    df 
} 

जब मैं के रूप में चलाने:

a2 <- weighted_mean_cols(aggdf, c("fac1","fac2","fac3"), c("col1","col2","col3"),"w") 

मैं अच्छा प्रदर्शन मिलता है, और कुछ हद तक पुन: प्रयोज्य, सुरुचिपूर्ण कोड।

+3

ढेर और [इस सवाल] में plyr अनुकूलन युक्तियों का ढेर कर रहे हैं (http://stackoverflow.com/questions/3685492/r-speeding-up-group-by-operations)। साथ ही, यह न भूलें कि आप इसे 'foreach' पैकेज से जोड़कर समानांतर में 'ddply' चला सकते हैं। –

+0

ने देखा है - मुझे पसंद की चाल की कोशिश की, न कि मैंने नहीं किया। इसके बजाए, मैं उपर्युक्त संपादन के साथ गया जो बेस आर का उपयोग करता है, काफी लचीला रहता है, और जल्दी से निष्पादित करता है (अभी भी 2 मिनट से कम)। अभी भी एक स्पष्टीकरण से प्यार होगा कि यह ddply में धीमा क्यों है - वाक्यविन्यास और समांतरता सुविधाओं से प्यार है! – evanrsparks

+4

'ddply' इतना धीमा है क्योंकि यह डेटा फ्रेम के साथ काम करता है, जो दुर्भाग्य से धीमे हैं। तेजी से दृष्टिकोण सीधे वैक्टर के साथ काम करते हैं, जो बहुत तेज हैं – hadley

उत्तर

2

यदि आप अपने संपादन का उपयोग करने जा रहे हैं, तो rowsum का उपयोग क्यों न करें और स्वयं को निष्पादन समय के कुछ मिनट बचाएं?

nr <- 2e6 
nc <- 3 
aggdf <- data.frame(matrix(rnorm(nr*nc),nr,nc), 
        matrix(sample(100,nr*nc,TRUE),nr,nc), rnorm(nr)) 
colnames(aggdf) <- c("col1","col2","col3","fac1","fac2","fac3","w") 

system.time({ 
aggsums <- rowsum(data.frame(aggdf[,c("col1","col2","col3")]*aggdf$w,w=aggdf$w), 
    interaction(aggdf[,c("fac1","fac2","fac3")])) 
agg_wtd_mean <- aggsums[,1:3]/aggsums[,4] 
}) 
# user system elapsed 
# 16.21 0.77 16.99 
+0

यदि आप इस उत्तर को अप-वोट करते हैं, तो [मरेक का उत्तर] (http://stackoverflow.com/questions/3685492/r-speeding-up-group-by-operations/3686241#3686241) को अप-वोट करना सुनिश्चित करें। .. –

+0

यह अच्छा और कुशल है, धन्यवाद! मेरा असली उद्देश्य यहां यह जानना है कि उस ऑपरेशन को डीडीपी में इतना धीमा कर देता है, लेकिन मुझे लगता है कि मैं कुछ प्रोफाइलिंग कर सकता हूं और पता लगा सकता हूं कि क्यों। – evanrsparks

5

हालांकि ddply लालित्य और कोड की आसानी के लिए हरा करना मुश्किल है, मुझे लगता है कि बड़े डेटा के लिए, tapply बहुत तेज है। आपके मामले में, मैं

do.call("cbind", list((w <- tapply(..)), tapply(..))) 

डॉट्स और संभवतः प्रश्न की दोषपूर्ण समझ के लिए खेद है; लेकिन मैं थोड़ी देर में हूं और लगभग पांच मिनट में बस पकड़ना चाहिए!

संबंधित मुद्दे