दिलचस्प पोस्ट
टुकड़ा से कस्टम एक्शनबार शीर्षक सेट करना dplyr :: group_by_ कई चर नामों के चरित्र स्ट्रिंग इनपुट के साथ एकल पंक्ति के लिए edittext प्रतिबंधित करें मैं फ्लास्क के साथ उपयोगकर्ता एजेंट कैसे प्राप्त करूं? एंड्रॉइड एडिटटेक्स्ट ऑनक्लिक लेस्टनर ASP.Net वेब फ़ॉर्म के साथ कैसल विंडसर का उपयोग कैसे करें? अनुप्रयोग जो ओअथ और जावास्क्रिप्ट का उपयोग करता है डापर के साथ कार्य पद्धति का यूनिट कैसे कार्यान्वित करें? स्टोरीबोर्ड के भीतर एक मूल दृश्य नियंत्रक को बच्चे को देखने नियंत्रकों को लिंक करना PHP को उप निर्देशिकाओं सहित फ़ाइल प्रविष्ट करें JavaFX की संस्करण संख्या कैसे प्राप्त करें? पासवर्ड की शक्ति को मान्य करने के लिए रेगेक्स फ़ाइल को संग्रह के लिए बनाया गया था जो कि वास्तुकला से जुड़े नहीं है (i386) आईटरेटिव डीएफएस बनाम रिकर्सिव डीएफएस और विभिन्न तत्वों के आदेश डिस्क ड्राइव के बारे में जानकारी प्राप्त करें, विंडोज़ 7 पर – 32 बिट सिस्टम

आर में लूप ऑपरेशन को गति दें

मैं आर में एक बड़ी कार्यक्षमता समस्या है। मैंने उस फ़ंक्शन को लिखा है जो किसी data.frame पर data.frame है। data.frame वस्तु यह केवल data.frame एक नया कॉलम जोड़ता है और कुछ जमा करता है (सरल ऑपरेशन) data.frame में लगभग 850K पंक्तियाँ हैं मेरा पीसी अभी भी काम कर रहा है (लगभग 10h अब) और मुझे रनटाइम के बारे में कोई जानकारी नहीं है

 dayloop2 <- function(temp){ for (i in 1:nrow(temp)){ temp[i,10] <- i if (i > 1) { if ((temp[i,6] == temp[i-1,6]) & (temp[i,3] == temp[i-1,3])) { temp[i,10] <- temp[i,9] + temp[i-1,10] } else { temp[i,10] <- temp[i,9] } } else { temp[i,10] <- temp[i,9] } } names(temp)[names(temp) == "V10"] <- "Kumm." return(temp) } 

किसी भी विचार कैसे इस ऑपरेशन को गति?

Solutions Collecting From Web of "आर में लूप ऑपरेशन को गति दें"

सबसे बड़ी समस्या और अप्रभावीता की जड़ें डेटा को अनुक्रमणित कर रही हैं। फ्रेम, मेरा मतलब है कि ये सभी पंक्तियां जहां आप temp[,] उपयोग करते हैं
जितना संभव हो उतना इस से बचने की कोशिश करें। मैंने अपना फ़ंक्शन लिया, इंडेक्सिंग में परिवर्तन किया और यहाँ संस्करण_ए

 dayloop2_A <- function(temp){ res <- numeric(nrow(temp)) for (i in 1:nrow(temp)){ res[i] <- i if (i > 1) { if ((temp[i,6] == temp[i-1,6]) & (temp[i,3] == temp[i-1,3])) { res[i] <- temp[i,9] + res[i-1] } else { res[i] <- temp[i,9] } } else { res[i] <- temp[i,9] } } temp$`Kumm.` <- res return(temp) } 

जैसा कि आप देख सकते हैं कि मैं वेक्टर res निर्माण करता हूं जो परिणामों को इकट्ठा करता है अंत में मैं इसे data.frame और मुझे नामों के साथ गड़बड़ करने की आवश्यकता नहीं है I तो यह कितना अच्छा है?

मैं प्रत्येक फ़ंक्शन को data.frame लिए data.frame nrowdata.frame साथ 1,000 से 10,000 तक 1,000 से 1,000 और data.frame साथ समय का समय। समय

 X <- as.data.frame(matrix(sample(1:10, n*9, TRUE), n, 9)) system.time(dayloop2(X)) 

परिणाम है

प्रदर्शन

आप देख सकते हैं कि आपका संस्करण nrow(X) से तेजी से निर्भर करता है संशोधित संस्करण में रैखिक संबंध है, और सरल lm मॉडल का अनुमान है कि 850,000 पंक्तियों के लिए गणना में 6 मिनट और 10 सेकंड लगते हैं।

वेक्टरिंग की शक्ति

जैसा कि शेन और कैलिमो ने अपने जवाब में कहा है कि वेक्टरिंग बेहतर प्रदर्शन की कुंजी है। अपने कोड से आप लूप के बाहर जा सकते हैं:

  • कंडीशनिंग
  • परिणाम का प्रारंभ (जो temp[i,9] )

यह इस कोड की ओर जाता है

 dayloop2_B <- function(temp){ cond <- c(FALSE, (temp[-nrow(temp),6] == temp[-1,6]) & (temp[-nrow(temp),3] == temp[-1,3])) res <- temp[,9] for (i in 1:nrow(temp)) { if (cond[i]) res[i] <- temp[i,9] + res[i-1] } temp$`Kumm.` <- res return(temp) } 

इस कार्य के लिए परिणाम की तुलना करें, यह समय 10 से 10,000 से 100,000 तक nrow लिए है।

प्रदर्शन

देखते ट्यूनिंग

एक अन्य चिमटा एक लूप इंडेक्सिंग temp[i,9] में बदलना है res[i] (जो i-th लूप इट्रितेशन में सटीक हैं)। यह एक सदिश को अनुक्रमणित करने और एक data.frame अनुक्रमणित करने में data.frame
दूसरी बात: जब आप लूप को देखते हैं तो आप देख सकते हैं कि i सभी पर लूप की कोई ज़रूरत नहीं है, लेकिन केवल उन लोगों के लिए जो शर्त लगाते हैं
तो अब हम शुरू करें

 dayloop2_D <- function(temp){ cond <- c(FALSE, (temp[-nrow(temp),6] == temp[-1,6]) & (temp[-nrow(temp),3] == temp[-1,3])) res <- temp[,9] for (i in (1:nrow(temp))[cond]) { res[i] <- res[i] + res[i-1] } temp$`Kumm.` <- res return(temp) } 

जो प्रदर्शन आप अत्यधिक प्राप्त करते हैं वह डेटा संरचना पर निर्भर करता है। संक्षेप में – शर्त में TRUE मूल्यों के प्रतिशत पर। मेरे सिम्युलेटेड डेटा के लिए यह एक सेकंड के नीचे 850,000 पंक्तियों के लिए गणना समय लेता है।

प्रदर्शन

मैं चाहता हूं कि आप आगे जा सकें, मुझे कम से कम दो चीजें हैं जो कर सकते हैं:

  • सशर्त cumsum करने के लिए एक C कोड लिखें
  • अगर आपको पता है कि आपके डेटा में अधिकतम अनुक्रम बड़ा नहीं है, तो आप लूप को वेक्टरयुक्त बदल सकते हैं, जबकि कुछ ऐसा है

     while (any(cond)) { indx <- c(FALSE, cond[-1] & !cond[-n]) res[indx] <- res[indx] + res[which(indx)-1] cond[indx] <- FALSE } 

सिमुलेशन और आंकड़ों के लिए इस्तेमाल किया गया कोड GitHub पर उपलब्ध है ।

आर कोड को गति देने के लिए सामान्य रणनीतियां

सबसे पहले, यह समझें कि धीमे भाग वास्तव में कहाँ है उस कोड को अनुकूलित करने की कोई आवश्यकता नहीं है जो धीमे गति से नहीं चल रहा है थोड़ी मात्रा में कोड के लिए, बस इसके माध्यम से सोच कर काम कर सकते हैं अगर वह विफल हो जाता है, RProf और इसी तरह के प्रोफाइल उपकरण उपयोगी हो सकते हैं।

एक बार जब आप बाधा को समझते हैं, तो आप क्या चाहते हैं, इसके लिए अधिक कुशल एल्गोरिदम के बारे में सोचें। यदि संभव हो तो गणना केवल एक बार चलनी चाहिए, इसलिए:

  • बार-बार पुनर्गणना के बजाय परिणामों को स्टोर करें और उन तक पहुंचें
  • लूप के बाहर गैर-पाश-आधारित गणना लें
  • उन गणनाओं से बचें जो आवश्यक नहीं हैं (उदाहरण के लिए, निश्चित खोजों के साथ नियमित अभिव्यक्ति का प्रयोग न करें )

अधिक कुशल कार्यों का उपयोग करना मध्यम या बड़े गति लाभ पैदा कर सकता है। उदाहरण के लिए, paste0 एक छोटी सी क्षमता हासिल करता है, लेकिन। .colSums() और उसके रिश्तेदार कुछ हद तक स्पष्ट लाभ उत्पन्न करते हैं। mean विशेष रूप से धीमा है

तो आप कुछ विशेष रूप से सामान्य परेशानियों से बच सकते हैं:

  • cbind आपको बहुत धीमा कर देगा
  • अपने डेटा संरचनाओं को प्रारंभ करें, फिर उन्हें हर बार विस्तार करने की बजाय , उन्हें भरें
  • पूर्व-आवंटन के साथ भी, आप एक पास-बाय-मान दृष्टिकोण के बजाय पास-बाय-रेफरेंस ऐप पर स्विच कर सकते हैं, लेकिन यह परेशानी के लायक नहीं हो सकता है।
  • बचने के लिए अधिक नुकसान के लिए आर इन्फर्नो पर नज़र डालें।

बेहतर सदिशीकरण की कोशिश करें, जो अक्सर लेकिन हमेशा मदद नहीं कर सकता है इस संबंध में, स्वाभाविक रूप से ifelse आदेश जैसे ifelse , diff , और जैसे आज्ञाओं के परिवार को apply तुलना में अधिक सुधार प्रदान करेगा (जो अच्छी तरह से लिखा गया लूप पर कोई गति बढ़ाने के लिए बहुत कम प्रदान करते हैं)।

आप आर फ़ंक्शन के लिए अधिक जानकारी प्रदान करने का भी प्रयास कर सकते हैं। उदाहरण के लिए, vapply बजाय vapply उपयोग करें, और टेक्स्ट-आधारित डेटा में पढ़ते समय colClasses निर्दिष्ट करें। स्पीड गेन वेरिएबल होगी, जिससे आपको अनुमान लगाने में कितना अनुमान लगाया जाएगा।

इसके बाद, अनुकूलित पैकेजों पर विचार करें: data.table पैकेज भारी गति लाभ पैदा कर सकता है, जहां इसका उपयोग डेटा हेरफेर में और बड़ी मात्रा में डेटा ( fread ) को पढ़ने में संभव है।

इसके बाद, कॉल करने के अधिक कुशल माध्यमों के माध्यम से गति लाभ की कोशिश करें:

  • अपनी आर स्क्रिप्ट को संकलित करें या बस और समय के संकलन के लिए कॉन्सर्ट में Ra और jit संकुल का उपयोग करें (डीर्क का इस प्रस्तुति में एक उदाहरण है)।
  • सुनिश्चित करें कि आप एक अनुकूलित बीएलएएस का उपयोग कर रहे हैं। इन-बोर्ड-स्पीड गेनस प्रदान करते हैं। ईमानदारी से, यह शर्म की बात है कि आर संस्थापित होने पर सबसे प्रभावी लाइब्रेरी का उपयोग नहीं करता है। उम्मीद है कि क्रांति आर उन कामों में योगदान करेगा, जो उन्होंने पूरे समुदाय में वापस किया है।
  • रेडफोर्ड नेल ने अनुकूलन का एक गुच्छा किया है, जिनमें से कुछ को आर कोर में अपनाया गया था, और कई अन्य लोगों को पीक़आर में बंद कर दिया गया था ।

और आखिरकार, अगर उपरोक्त सभी को आपको जितनी जल्दी जरूरत पड़ने पर नहीं मिलती है, आपको धीमे कोड स्निपेट के लिए तेज़ भाषा में स्थानांतरित करने की आवश्यकता हो सकती है। Rcpp और inline का संयोजन सी ++ कोड के साथ अल्गोरिदम का सबसे धीमा हिस्सा विशेष रूप से आसान बनाता है। उदाहरण के लिए, ऐसा करने पर मेरा पहला प्रयास है , और यह अत्यधिक अनुकूल आर समाधान भी दूर करता है

यदि आप अभी भी परेशानियों के साथ छोड़ दिया है, तो आपको अधिक कंप्यूटिंग शक्ति की आवश्यकता है समांतरकरण ( http://cran.r-project.org/web/views/HighPerformanceComputing.html ) या GPU- आधारित समाधान ( gpu-tools ) में भी देखें।

अन्य मार्गदर्शन के लिए लिंक

यदि आप छोरों के for उपयोग कर रहे हैं, तो आप सबसे अधिक संभावना कोडिंग आर कर रहे हैं जैसे कि यह सी या जावा या कुछ और था ठीक से vectorised है कि आर कोड बहुत तेज है

उदाहरण के लिए इन दो सरल बिट्स कोड को क्रम में 10,000 पूर्णांकियों की सूची बनाने के लिए लें:

पहला कोड उदाहरण यह है कि एक पारंपरिक कोडन प्रतिमान का उपयोग करके एक लूप कैसे कोड करेगा। इसे पूरा करने में 28 सेकंड लगते हैं

 system.time({ a <- NULL for(i in 1:1e5)a[i] <- i }) user system elapsed 28.36 0.07 28.61 

आप पूर्व-आवंटित स्मृति की सरल कार्रवाई से लगभग 100 बार सुधार प्राप्त कर सकते हैं:

 system.time({ a <- rep(1, 1e5) for(i in 1:1e5)a[i] <- i }) user system elapsed 0.30 0.00 0.29 

लेकिन बृहदान्त्र ऑपरेटर का उपयोग करके आधार आर वेक्टर ऑपरेशन का उपयोग करना : यह ऑपरेशन लगभग तात्कालिक है:

 system.time(a <- 1:1e5) user system elapsed 0 0 0 

यह अनुक्रमित या नेस्टेड ifelse() स्टेटमेंट्स का उपयोग करके छोरों को छोड़कर बहुत तेज़ हो सकता है

 idx <- 1:nrow(temp) temp[,10] <- idx idx1 <- c(FALSE, (temp[-nrow(temp),6] == temp[-1,6]) & (temp[-nrow(temp),3] == temp[-1,3])) temp[idx1,10] <- temp[idx1,9] + temp[which(idx1)-1,10] temp[!idx1,10] <- temp[!idx1,9] temp[1,10] <- temp[1,9] names(temp)[names(temp) == "V10"] <- "Kumm." 

अपने जवाब के अंत में वर्णित एरी के रूप में, Rcpp और inline पैकेज चीजों को तेजी से बनाने के लिए अविश्वसनीय रूप से आसान बनाते हैं। एक उदाहरण के रूप में, इस inline कोड की कोशिश करें (चेतावनी: परीक्षण नहीं किया गया है):

 body <- 'Rcpp::NumericMatrix nm(temp); int nrtemp = Rccp::as<int>(nrt); for (int i = 0; i < nrtemp; ++i) { temp(i, 9) = i if (i > 1) { if ((temp(i, 5) == temp(i - 1, 5) && temp(i, 2) == temp(i - 1, 2) { temp(i, 9) = temp(i, 8) + temp(i - 1, 9) } else { temp(i, 9) = temp(i, 8) } } else { temp(i, 9) = temp(i, 8) } return Rcpp::wrap(nm); ' settings <- getPlugin("Rcpp") # settings$env$PKG_CXXFLAGS <- paste("-I", getwd(), sep="") if you want to inc files in wd dayloop <- cxxfunction(signature(nrt="numeric", temp="numeric"), body-body, plugin="Rcpp", settings=settings, cppargs="-I/usr/include") dayloop2 <- function(temp) { # extract a numeric matrix from temp, put it in tmp nc <- ncol(temp) nm <- dayloop(nc, temp) names(temp)[names(temp) == "V10"] <- "Kumm." return(temp) } 

#include ing चीजों के लिए ऐसी ही एक प्रक्रिया है, जहां आप एक पैरामीटर पास करते हैं

 inc <- '#include <header.h> 

के लिए cxxfunction, के रूप include=inc इस बारे में वास्तव में क्या अच्छा है कि यह आपके लिए सभी लिंक और संकलन करता है, इसलिए प्रोटोटाइप वास्तव में तेजी से है

अस्वीकरण: मुझे पूरी तरह से आश्वस्त नहीं है कि टीएमपी का वर्ग अंकीय और संख्यात्मक मैट्रिक्स या कुछ और होना चाहिए। लेकिन मुझे यकीन है कि

संपादित करें: यदि आपको इसके बाद भी अधिक गति की आवश्यकता है, तो OpenMP C++ लिए एक समानांतर सुविधा C++ । मैंने इसे inline से प्रयोग करने की कोशिश नहीं की है, लेकिन इसे काम करना चाहिए यह विचार होगा कि, n कोर के मामले में, लूप पुनरावृत्ति k द्वारा किया जाना चाहिए k % n मैटलॉफ़ के द आर्ट ऑफ आर प्रोग्रामिंग में एक उपयुक्त परिचय पाया गया है, जो यहां उपलब्ध है , अध्याय 16 में, सी को रिसोइंग

मैं कोड को फिर से लिखना पसंद नहीं करता … इसके अलावा बेशक इफेल और लैपली बेहतर विकल्प होते हैं लेकिन कभी-कभी उस फिट को बनाना मुश्किल होता है

अक्सर मैं data.frames का उपयोग करता हूं क्योंकि कोई भी सूचियों का उपयोग करता है जैसे कि df$var[i]

यहां एक उदाहरण बनाया गया है:

 nrow=function(x){ ##required as I use nrow at times. if(class(x)=='list') { length(x[[names(x)[1]]]) }else{ base::nrow(x) } } system.time({ d=data.frame(seq=1:10000,r=rnorm(10000)) d$foo=d$r d$seq=1:5 mark=NA for(i in 1:nrow(d)){ if(d$seq[i]==1) mark=d$r[i] d$foo[i]=mark } }) system.time({ d=data.frame(seq=1:10000,r=rnorm(10000)) d$foo=d$r d$seq=1:5 d=as.list(d) #become a list mark=NA for(i in 1:nrow(d)){ if(d$seq[i]==1) mark=d$r[i] d$foo[i]=mark } d=as.data.frame(d) #revert back to data.frame }) 

data.frame संस्करण:

  user system elapsed 0.53 0.00 0.53 

सूची संस्करण:

  user system elapsed 0.04 0.00 0.03 

डेटा से अधिक वैक्टर की सूची का उपयोग करने के लिए 17x बार तेज़।

इस बारे में कोई भी टिप्पणी क्यों आंतरिक रूप से डेटा। फ्रेम इस संबंध में धीमे हैं? ऐसा लगता है कि वे सूचियों की तरह कार्य करते हैं …

भी तेज कोड के लिए इस class(d)='list' बजाय d=as.list(d) और class(d)='data.frame'

 system.time({ d=data.frame(seq=1:10000,r=rnorm(10000)) d$foo=d$r d$seq=1:5 class(d)='list' mark=NA for(i in 1:nrow(d)){ if(d$seq[i]==1) mark=d$r[i] d$foo[i]=mark } class(d)='data.frame' }) head(d) 

आर में, आप अक्सर फ़ैशन-अप लूप प्रोसेसिंग परिवार फ़ैक्ट्स apply कर apply हैं (आपके मामले में, यह शायद replicate )। plyr पैकेज पर एक नज़र डालें जो प्रगति बार प्रदान करता है।

एक अन्य विकल्प को छोरों से पूरी तरह से बचाना है और उन्हें वेक्टरयुक्त अंकगणित के साथ बदलना है। मुझे यकीन नहीं है कि आप वास्तव में क्या कर रहे हैं, लेकिन आप संभवत: एक बार में सभी पंक्तियों पर अपने फ़ंक्शन लागू कर सकते हैं:

 temp[1:nrow(temp), 10] <- temp[1:nrow(temp), 9] + temp[0:(nrow(temp)-1), 10] 

यह बहुत तेज़ हो जाएगा, और फिर आप अपनी स्थिति के साथ पंक्तियों को फ़िल्टर कर सकते हैं:

 cond.i <- (temp[i, 6] == temp[i-1, 6]) & (temp[i, 3] == temp[i-1, 3]) temp[cond.i, 10] <- temp[cond.i, 9] 

वेक्टोरिज्ड अंकगणित की समस्या के बारे में अधिक समय और सोचने की आवश्यकता होती है, लेकिन फिर आप कभी-कभी निष्पादन समय में परिमाण के कई आदेश बचा सकते हैं।

data.table साथ प्रसंस्करण data.table एक व्यवहार्य विकल्प है:

 n <- 1000000 df <- as.data.frame(matrix(sample(1:10, n*9, TRUE), n, 9)) colnames(df) <- paste("col", 1:9, sep = "") library(data.table) dayloop2.dt <- function(df) { dt <- data.table(df) dt[, Kumm. := { res <- .I; ifelse (res > 1, ifelse ((col6 == shift(col6, fill = 0)) & (col3 == shift(col3, fill = 0)) , res <- col9 + shift(res) , # else res <- col9 ) , # else res <- col9 ) } ,] res <- data.frame(dt) return (res) } res <- dayloop2.dt(df) m <- microbenchmark(dayloop2.dt(df), times = 100) #Unit: milliseconds # expr min lq mean median uq max neval #dayloop2.dt(df) 436.4467 441.02076 578.7126 503.9874 575.9534 966.1042 10 

यदि आप फ़िल्टरिंग शर्तों से संभव लाभ की उपेक्षा करते हैं, तो यह बहुत तेज है जाहिर है, यदि आप डेटा के सबसेट पर गणना कर सकते हैं, तो यह मदद करता है