मैंने डेटा फ़्रेम input
में फ़ंक्शन लागू करने के लिए एक कोड लिखा था:
set.seed(1234)
n = 5000000
input <- as.matrix(data.frame(c1 = sample(1:10, n, replace = T), c2 = sample(1:10, n, replace = T), c3 = sample(1:10, n, replace = T), c4 = sample(1:10, n, replace = T)))
system.time(
test <- input %>%
split(1:nrow(input)) %>%
map(~ func1(.x, 2, 2, "test_1")) %>%
do.call("rbind", .))
## Here is the function used:
func1 <- function(dataC, PR, DB, MT){
c1 <- as.vector(dataC[1])
c2 <- as.vector(dataC[2])
c3 <- as.vector(dataC[3])
c4 <- as.vector(dataC[4])
newc1 <- -999
newc2 <- -999
if(MT=="test_1"){
listC <- expand.grid(x = c((c1 - PR) : (c1 - 1)), y = c((c2 + 1) : (c2 + PR)))
V1 <- mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * sqrt(2) * DB
listC <- expand.grid(x = c((c1 - 1) : (c1 + 1)), y = c((c2 + 1) : (c2 + PR)))
V2 <- mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * DB
listC <- expand.grid(x = c((c1 + 1) : (c1 + PR)), y = c((c2 + 1) : (c2 + PR)))
V3 <- mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * sqrt(2) * DB
listC <- expand.grid(x = c((c1 - PR) : (c1 - 1)), y = c((c2 - 1) : (c2 + 1)))
V4 <- mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * DB
V5 <- 0
listC <- expand.grid(x = c((c1 + 1) : (c1 + PR)), y = c((c2 - 1) : (c2 + 1)))
V6 <- mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * DB
listC <- expand.grid(x = c((c1 - PR) : (c1 - 1)), y = c((c2 - PR) : (c2 - 1)))
V7 <- mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * sqrt(2) * DB
listC <- expand.grid(x = c((c1 - 1) : (c1 + 1)), y = c((c2 - PR) : (c2 - 1)))
V8 <- mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * DB
listC <- expand.grid(x = c((c1 + 1) : (c1 + PR)), y = c((c2 - PR) : (c2 - 1)))
V9 <- mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * sqrt(2) * DB
} else if(MT=="test_2"){
listC <- expand.grid(x = c((c1 - PR) : (c1 - 1)), y = c((c2 + 1) : (c2 + PR)))
V1 <- harmonic.mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * sqrt(2) * DB
listC <- expand.grid(x = c((c1 - 1) : (c1 + 1)), y = c((c2 + 1) : (c2 + PR)))
V2 <- harmonic.mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * DB
listC <- expand.grid(x = c((c1 + 1) : (c1 + PR)), y = c((c2 + 1) : (c2 + PR)))
V3 <- harmonic.mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * sqrt(2) * DB
listC <- expand.grid(x = c((c1 - PR) : (c1 - 1)), y = c((c2 - 1) : (c2 + 1)))
V4 <- harmonic.mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * DB
V5 <- 0
listC <- expand.grid(x = c((c1 + 1) : (c1 + PR)), y = c((c2 - 1) : (c2 + 1)))
V6 <- harmonic.mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * DB
listC <- expand.grid(x = c((c1 - PR) : (c1 - 1)), y = c((c2 - PR) : (c2 - 1)))
V7 <- harmonic.mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * sqrt(2) * DB
listC <- expand.grid(x = c((c1 - 1) : (c1 + 1)), y = c((c2 - PR) : (c2 - 1)))
V8 <- harmonic.mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * DB
listC <- expand.grid(x = c((c1 + 1) : (c1 + PR)), y = c((c2 - PR) : (c2 - 1)))
V9 <- harmonic.mean(sample(1:10, size = dim(listC)[1], replace = TRUE)) * sqrt(2) * DB
}
tot <- sum(c(1/V1, 1/V2, 1/V3, 1/V4, 1/V6, 1/V7, 1/V8, 1/V9), na.rm = TRUE)
mat_V <- matrix(data = c((1/V1)/tot, (1/V2)/tot, (1/V3)/tot, (1/V4)/tot, V5,
(1/V6)/tot, (1/V7)/tot, (1/V8)/tot, (1/V9)/tot), nrow = 3, ncol = 3, byrow = TRUE)
while((newc1 == -999 && newc2 == -999) || (c3 == newc1 && c4 == newc2)){
if(c3 == newc1 && c4 == newc2){
mat_V[choiceC[1], choiceC[2]] <- NaN
## print(mat_V)
}
choiceC <- which(mat_V == max(mat_V, na.rm = TRUE), arr.ind = TRUE)
## print(choiceC)
## If there are several maximum values
if(nrow(choiceC) > 1){
choiceC <- choiceC[sample(1:nrow(choiceC), 1), ]
}
if(choiceC[1]==1 & choiceC[2]==1){
newC <- matrix(c(x = c1 - 1, y = c2 + 1), ncol = 2)
} else if(choiceC[1]==1 & choiceC[2]==2){
newC <- matrix(c(x = c1, y = c2 + 1), ncol = 2)
} else if(choiceC[1]==1 & choiceC[2]==3){
newC <- matrix(c(x = c1 + 1, y = c2 + 1), ncol = 2)
} else if(choiceC[1]==2 & choiceC[2]==1){
newC <- matrix(c(x = c1 - 1, y = c2), ncol = 2)
} else if(choiceC[1]==2 & choiceC[2]==3){
newC <- matrix(c(x = c1 + 1, y = c2), ncol = 2)
} else if(choiceC[1]==3 & choiceC[2]==1){
newC <- matrix(c(x = c1 - 1, y = c2 - 1), ncol = 2)
} else if(choiceC[1]==3 & choiceC[2]==2){
newC <- matrix(c(x = c1, y = c2 - 1), ncol = 2)
} else if(choiceC[1]==3 & choiceC[2]==3){
newC <- matrix(c(x = c1 + 1, y = c2 - 1), ncol = 2)
}
newc1 <- as.vector(newC[,1])
newc2 <- as.vector(newC[,2])
}
return(newC)
}
कोड छोटे डेटासेट के लिए काम करता है लेकिन जब डेटा फ़्रेम में 1 मिलियन से अधिक पंक्तियाँ होती हैं, तो यह बहुत धीमा होता है। मुझे लगता है कि फ़ंक्शन में कोड की कई पंक्तियाँ दोहराई जाती हैं (जैसे, कंडीशन if else
) जो गति को कम करती हैं। क्या फ़ंक्शन में सभी गणनाओं को एक साथ करने के तरीके हैं? मैं किसी भी सलाह के लिए वास्तव में सराहना करता हूं।
1 उत्तर
पहले थोड़ा कठिन प्यार लेकिन मैं आपको अपने आधारों को कवर करने के लिए दृढ़ता से प्रोत्साहित करता हूं, आपका कोड बुरी प्रथाओं का केंद्र है और आपको वेक्टराइजेशन आदि का अध्ययन करने में थोड़ा समय व्यतीत करके एक बड़ा आरओआई प्राप्त होगा... इस पर भी पोस्ट करने पर विचार करें < a href="https://codereview.stackexchange.com/questions/tagged/r">https://codereview.stackexchange.com/questions/tagged/r अगली बार क्योंकि यह इसके लिए अधिक उपयुक्त प्रश्न है वहां।
आपकी अड़चन नेस्टेड ifs नहीं है लेकिन expand.grid
का अपर्याप्त उपयोग है।
आप अपने कोड में expand.grid
के माध्यम से डेटा फ़्रेम बनाते हैं, जिसे आप अनुचित तरीके से listC
कहते हैं (वे सूचियां नहीं हैं)। फिर यह महंगा data.frame केवल इसकी पंक्तियों की संख्या के लिए उपयोग किया जाता है, जो आपको dim(listC)[1]
के साथ मिलता है जो कि अधिक मुहावरेदार टाइप nrow(listC)
होगा।
यह मान (dim(listC)[1]
) व्यवहार में केवल PR^2
या 3*PR
हो सकता है, इसलिए आप पहले उनकी गणना कर सकते हैं और उनका पुन: उपयोग कर सकते हैं।
नेस्टेड ifs को नेस्टेड स्विच स्टेटमेंट से बदला जा सकता है, अधिक पठनीय, और पहली पसंद का परीक्षण करके केवल एक बार हम और अधिक कुशल होते हैं।
यह हमें यह देखने की अनुमति देता है कि आप अपने कोड में एक शर्त भूल गए हैं। नीचे अपना बेहतर कोड देखें।
एक बार जब यह अधिक सुव्यवस्थित हो जाता है, तो हम देखते हैं कि हम वास्तव में इसे केवल newC <- c(c1 - 2 + choice[2], c2 + 2 - choice[1])
से बदल सकते हैं।
अतिरिक्त अवलोकन
- अपने कोड पर टिप्पणी करें, हमारे लिए नहीं, आपके लिए (और फिर हमारे लिए जब आप कोई प्रश्न पोस्ट करने का निर्णय लेते हैं)
c2 <- as.vector(dataC[2])
कोc2 <- dataC[[2]]
से बदला जा सकता हैmatrix(c(x = 1, y = 2), ncol = 2)
के बजायt(c(1,2))
द्वारा 2 कॉलम और एक पंक्ति का एक मैट्रिक्स बनाया जा सकता है, लेकिन यदि आप अंत में उस परas.vector
का उपयोग करने जा रहे हैं, तोc(1,2)
करें। पहली जगह में- कोड को शायद और अधिक अनुकूलित किया जा सकता है
संशोधित कोड
func1 <- function(dataC, PR, DB, MT){
c1 <- dataC[[1]]
c2 <- dataC[[2]]
c3 <- dataC[[3]]
c4 <- dataC[[4]]
fun <- if(MT=="test_1") mean else if(MT=="test_2") harmonic.mean
fun2 <- function(size,mult)
fun(sample(1:10, size = size, replace = TRUE)) * mult
pr_sq <- PR^2
pr_3 <- 3*PR
sqrt_2_DB <- sqrt(2) * DB
V1 <- fun2(pr_sq, sqrt_2_DB)
V2 <- fun2(pr_3, DB)
V3 <- fun2(pr_sq, sqrt_2_DB)
V4 <- fun2(pr_3, DB)
V5 <- 0
V6 <- fun2(pr_3, DB)
V7 <- fun2(pr_sq, sqrt_2_DB)
V8 <- fun2(pr_3, DB)
V9 <- fun2(pr_sq, sqrt_2_DB)
inv <- 1/c(V1, V2, V3, V4, V6, V7, V8, V9)
tot <- sum(inv, na.rm = TRUE)
mat_V <- matrix(data = c(inv[1:4], V5, inv[5:8]) / tot,
nrow = 3, ncol = 3, byrow = TRUE)
newC <- NULL
while(is.null(newC) || identical(c(c3,c4), newC)){
if(identical(c(c3,c4), newC)){
mat_V[choiceC[1], choiceC[2]] <- NaN
## print(mat_V)
}
choiceC <- which(mat_V == max(mat_V, na.rm = TRUE), arr.ind = TRUE)
## print(choiceC)
## If there are several maximum values
if(nrow(choiceC) > 1){
choiceC <- choiceC[sample(1:nrow(choiceC), 1), ]
}
newC <- c(c1 - 2 + choiceC[2], c2 + 2 - choiceC[1])
# using switch it would have been
# newC <- switch(choiceC[1],
# `1` = switch(choiceC[2],
# `1` = c(x = c1 - 1, y = c2 + 1),
# `2` = c(x = c1, y = c2 + 1),
# `3` = c(x = c1 + 1, y = c2 + 1)),
# `2` = switch(choiceC[2],
# `1` = c(x = c1 - 1, y = c2),
# `2` = c(x = c1, y = c2), # you were missing this one
# `3` = c(x = c1 + 1, y = c2)),
# `3` = switch(choiceC[2],
# `1` = c(x = c1 - 1, y = c2 - 1),
# `2` = c(x = c1, y = c2 - 1),
# `3` = c(x = c1 + 1, y = c2 - 1)))
}
t(newC)
}