En büyük sorun ve verimsizliğin kökü data.frame'i endekslemektir, yani kullandığınız tüm bu satırlar temp[,]
.
Bundan mümkün olduğunca kaçınmaya çalışın. İşlevinizi aldım, indekslemeyi değiştirdim ve burada 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)
}
Gördüğünüz gibi res
sonuçları toplayan vektör oluşturuyorum. Sonunda ekliyorum data.frame
ve isimleri karıştırmam gerekmiyor. Peki ne kadar iyi?
Her işlevi 1.000 ila 10.000 data.frame
ile nrow
1.000 için çalıştırıyorum vesystem.time
X <- as.data.frame(matrix(sample(1:10, n*9, TRUE), n, 9))
system.time(dayloop2(X))
Sonuç:
Sürümünüzün katlanarak bağlı olduğunu görebilirsiniz nrow(X)
. Modifiye edilmiş versiyonun doğrusal bir ilişkisi vardır ve basit lm
model 850.000 satırlık hesaplamanın 6 dakika 10 saniye sürdüğünü tahmin eder.
Vektörleştirmenin gücü
Shane ve Calimo'nun cevaplarında belirttiği gibi, vektörleşme daha iyi performans için bir anahtardır. Kodunuzdan döngü dışında hareket edebilirsiniz:
- şartlandırma
- sonuçların başlatılması (ki bunlar
temp[i,9]
)
Bu, bu koda götürür
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)
}
Bu işlevlerin sonuçlarını karşılaştırın, bu sefer nrow
10.000'den 100.000'e 10.000'e kadar.
Ayarlanan ayarlama
Başka bir çimdik bir döngü indeksleme değişen olduğu temp[i,9]
için res[i]
(tam i-inci döngünün aynı olan). Yine bir vektörü indekslemek ve a indekslemek arasındaki farktır data.frame
.
İkinci şey: döngüye baktığınızda, her şeyin üzerinde döngü yapmanın gerekmediğini görebilirsiniz i
, ancak sadece koşula uyanlar için.
İşte başlıyoruz
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)
}
Büyük ölçüde kazandığınız performans bir veri yapısına bağlıdır. Kesinlikle - koşuldaki TRUE
değerlerin yüzdesi üzerinde . Simüle edilmiş verilerim için bir saniyenin altındaki 850.000 satır için hesaplama süresi gerekir.
Daha ileri gidebilmeni istiyorum, yapılabilecek en az iki şey görüyorum:
C
koşullu cumsum yapmak için bir kod yazın
veri maks dizinizde büyük olmadığını biliyorsanız, döngüyü vectorized olarak değiştirebilirsiniz.
while (any(cond)) {
indx <- c(FALSE, cond[-1] & !cond[-n])
res[indx] <- res[indx] + res[which(indx)-1]
cond[indx] <- FALSE
}
Simülasyonlar ve şekiller için kullanılan kod GitHub'da mevcuttur .