[英]R Programming: How to vectorize/speed up a for loop that need the previous value in each process
我正在做一個for循環來填充向量。 問題在於,在每個循環中,它都需要先前的值來繼續進行計算。
我正在使用包data.table,所以它是一個數據表。 R版本64位3.2.3
該表具有f Im做的for循環,但是我想知道是否有一種方法可以向量化或使該過程更麻煩,因此需要花費一些時間來運行。 我將解釋我試圖達到的目標。 首先,我有一個表,該表必須對此部分使用循環,因為我需要先前的值,因此無法對操作進行向量化。
數據表具有以下結構:
NUMDCRED FDES Distancia CURA NPV
0001 "2012-01-01" 11 0 1
0001 "2012-02-01" 12 0 2
0001 "2012-03-01" 13 1 2
0001 "2011-01-01" 14 1 3
0001 "2011-02-01" 15 1 3
0001 "2011-03-01" 16 1 2
0001 "2011-04-01" 10 0 5
0001 "2011-05-01" 11 0 4
0001 "2011-06-01" 12 0 6
0001 "2011-07-01" 13 1 3
0001 "2011-08-01" 14 1 2
0001 "2011-09-01" 15 1 2
0001 "2011-10-01" 16 1 1
0001 "2011-11-01" 17 1 3
0002 "2012-04-01" 11 0 6
0002 "2012-05-01" 12 0 5
0002 "2012-06-01" 13 1 4
0002 "2012-07-01" 14 1 3
0002 "2012-08-01" 15 1 3
0002 "2012-09-01" 16 1 3
0002 "2012-10-01" 10 0 3
0002 "2012-11-01" 11 0 4
0002 "2012-12-01" 12 0 4
0002 "2013-01-01" 13 1 2
0002 "2013-02-01" 14 1 2
0002 "2013-03-01" 15 1 3
0002 "2013-04-01" 16 1 3
該表按NUMDCRED和FDES(升序)排序(POBLACION_MOROSA6)。 我需要做的是創建另一個名為P.Moroso的變量,當第一個不同的NUMDCRED出現時該值設置為1,當條件NPV <4且Distancia> 12且Cura [i- 1]!= 1。 P.Moroso的值必須保留在每個記錄中,直到達到條件時它才更改,這意味着當第一個NUMDCRED出現時,P.Moroso的值將為1,對於下一個記錄也將為1。滿足條件時更改為P.Moroso + 1(2),然后將此值保留為每個記錄,依此類推。
該過程的輸出如下:
NUMDCRED FDES Distancia CURA NPV P.Moroso
0001 "2012-01-01" 11 0 1 1
0001 "2012-02-01" 12 0 2 1
0001 "2012-03-01" 13 1 2 2
0001 "2011-01-01" 14 1 3 2
0001 "2011-02-01" 15 1 3 2
0001 "2011-03-01" 16 1 2 2
0001 "2011-04-01" 10 0 5 2
0001 "2011-05-01" 11 0 4 2
0001 "2011-06-01" 12 0 6 2
0001 "2011-07-01" 13 1 3 3
0001 "2011-08-01" 14 1 2 3
0001 "2011-09-01" 15 1 2 3
0001 "2011-10-01" 16 1 1 3
0001 "2011-11-01" 17 1 3 3
0002 "2012-04-01" 11 0 6 1
0002 "2012-05-01" 12 0 5 1
0002 "2012-06-01" 13 1 4 2
0002 "2012-07-01" 14 1 3 2
0002 "2012-08-01" 15 1 3 2
0002 "2012-09-01" 16 1 3 2
0002 "2012-10-01" 10 0 3 2
0002 "2012-11-01" 11 0 4 2
0002 "2012-12-01" 12 0 4 2
0002 "2013-01-01" 13 1 2 3
0002 "2013-02-01" 14 1 2 3
0002 "2013-03-01" 15 1 3 3
0002 "2013-04-01" 16 1 3 3
目前,Im使用以下簡單的foor循環執行此操作:
PERIODO_MOROSO <- vector(mode = "numeric",length=N3)
isFirstNumdCred_Morosa6 <- (1:N3) %in% FIRST_NUMDCRED_INDEX_P.MOROSA6
for(i in 1:N3){
if(isFirstNumdCred_Morosa6[i]){
P.MOROSO <- 1
} else if(POBLACION_MOROSA6[i,NPV] < 4 & POBLACION_MOROSA6[i-1,CURA] ! =1 & POBLACION_MOROSA6[i,DISTANCIA_SALIDA] > 12){
P.MOROSO <- P.MOROSO + 1
}
PERIODO_MOROSO[i] <- P.MOROSO
}
POBLACION_MOROSA6$P.MOROSO <- PERIODO_MOROSO
變量isFirstNumdCred_Morosa6是一個邏輯向量,指示何時出現第一個不同的Numdcred。 我的foor循環的問題是,在處理大數據時速度很慢(我的表的行在900k到200萬之間。我嘗試使用帶有
ex[,date.seq.3:=ifelse( condition, shift(P.Moroso) +1 , P.Moroso)]
但這沒有用(首先我將所有的都分配給具有第一個不同NUMDCRED的行)
我也嘗試使用其他人在我之前發布的問題中告訴我的其他方法,但我做不到。 如果有人想看到我遇到的類似問題的解決方案,我會提出另一個問題的鏈接。
因此,總而言之,我想知道是否可以矢量化/加速此過程。 R編程:如何加快耗時2小時的循環以及耗費大量時間的原因
您不需要循環
ex <- read.table(header = TRUE, text = 'NUMDCRED FDES Distancia CURA NPV P.Moroso
0001 "2012-01-01" 11 0 1 1
0001 "2012-02-01" 12 0 2 1
0001 "2012-03-01" 13 1 2 2
0001 "2011-01-01" 14 1 3 2
0001 "2011-02-01" 15 1 3 2
0001 "2011-03-01" 16 1 2 2
0001 "2011-04-01" 10 0 5 2
0001 "2011-05-01" 11 0 4 2
0001 "2011-06-01" 12 0 6 2
0001 "2011-07-01" 13 1 3 3
0001 "2011-08-01" 14 1 2 3
0001 "2011-09-01" 15 1 2 3
0001 "2011-10-01" 16 1 1 3
0001 "2011-11-01" 17 1 3 3
0002 "2012-04-01" 11 0 6 1
0002 "2012-05-01" 12 0 5 1
0002 "2012-06-01" 13 1 4 2
0002 "2012-07-01" 14 1 3 2
0002 "2012-08-01" 15 1 3 2
0002 "2012-09-01" 16 1 3 2
0002 "2012-10-01" 10 0 3 2
0002 "2012-11-01" 11 0 4 2
0002 "2012-12-01" 12 0 4 2
0002 "2013-01-01" 13 1 2 3
0002 "2013-02-01" 14 1 2 3
0002 "2013-03-01" 15 1 3 3
0002 "2013-04-01" 16 1 3 3 ')
在基礎中,您可以將邏輯寫入函數
f <- function(data)
cumsum(with(data, Distancia > 12 & NPV <= 4 & c(0, CURA[-length(CURA)]) != 1)) + 1L
並將其應用於數據的子集
ex$P.Moroso2 <- unlist(by(ex, dd$NUMDCRED, f))
identical(ex$P.Moroso, ex$P.Moroso2)
# [1] TRUE
轉換為data.table,這看起來像
setDT(ex)[, P.Moroso3 :=
cumsum(Distancia > 12 & NPV <= 4 & shift(CURA, fill = 0) != 1) + 1L
, by = NUMDCRED]
# or Frank says this works, anyways
你的意思是這樣的...? (假設您的表名是“ TABLA”)
P.moroso = c(1)
NUMDCRED = TABLA$NUMDCRED
Cura = TABLA$Cura
NPV = TABLA$NPV
Distancia = TABLA$Distancia #right now, I just created vectors with the needed columns information
N = length (NUMEDRED)
contador = 1 #the counter set in 1
for (i in 2:N){
if (NUMDCRED[i-1] != NUMDCRED[i])
contador = 1 #sets contador in 1 again
else if ((NVP[i] <4) && (Distancia[i] > 12)&& (Cura[i-1] != 1))
contador = contador +1 #if the condition happens, increases contador in 1
P.moroso[i] = contador #append contador in P.moroso vector.
}
現在,您應該有了一個帶有所需數字的P.moroso向量。 最后,將其附加到表上:
TABLA$P.moroso = P.moroso
我認為我有一個快速的解決方案,但是我還沒有測試過,所以我真的不知道。 這是我的思考過程:
您可以先將數據除以NUMDCRED的值,因為每次NUMDCRED更改時P.Moroso的值始終從1開始。 將數據的每個子集放入列表中。
您現在可以使用lapply將函數應用於列表中的每個數據集。 首先,如果滿足您指定的條件,則創建一個TRUE列,如果未指定條件,則創建一個FALSE列。 然后,您可以對該列進行累加和並將其存儲為P.Moroso列。 我認為那應該是您想要的。
合並所有數據集。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.