सबसे बड़ी समस्या और अप्रभावीता की जड़ डेटा.फ्रेम को अनुक्रमित करना है, मेरा मतलब है कि यह सभी रेखाएं जहां आप उपयोग करते हैं temp[,]
।
जितना संभव हो इससे बचने की कोशिश करें। मैंने आपका कार्य लिया, अनुक्रमण को बदला और यहाँ version_A लिया
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
और मुझे नामों के साथ गड़बड़ करने की आवश्यकता नहीं है। तो कितना अच्छा है?
मैं के लिए प्रत्येक कार्य को चलाने के data.frame
साथ nrow
1,000 से 1,000 से 10,000 और साथ समय को मापनेsystem.time
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)
}
इस फ़ंक्शन के लिए परिणाम की तुलना करें, इस बार nrow
10,000 से 100,000 से 10,000 तक।
ट्यूनिंग ट्यूनिंग
एक और ट्विक एक लूप इंडेक्सिंग में बदलना temp[i,9]
है res[i]
(जो कि i-th लूप पुनरावृत्ति में समान है)। यह एक वेक्टर को अनुक्रमित करने और अनुक्रमणिका के बीच फिर से अंतर है 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 पंक्तियों के लिए अभिकलन समय लगता है।
मैं चाहता हूं कि आप आगे जा सकते हैं, मैं कम से कम दो चीजें देखता हूं जो किया जा सकता है:
C
सशर्त कमशॉट करने के लिए एक कोड लिखें
यदि आप जानते हैं कि आपके डेटा में अधिकतम अनुक्रम बड़ा नहीं है, तो आप लूप को बदलकर वेक्टरकृत कर सकते हैं, जबकि कुछ ऐसा है
while (any(cond)) {
indx <- c(FALSE, cond[-1] & !cond[-n])
res[indx] <- res[indx] + res[which(indx)-1]
cond[indx] <- FALSE
}
सिमुलेशन और आंकड़ों के लिए उपयोग किया जाने वाला कोड GitHub पर उपलब्ध है ।