2016-04-07 4 views
1

ベクトルを埋めるためにforループを実行しています。問題は、各ループで計算を続けるために以前の値が必要であるということです。Rプログラミング:各プロセスで以前の値を必要とするforループをベクトル化/スピードアップする方法

私はパッケージdata.tableを使用していますので、そのデータテーブルです。 Rバージョン64ビット3.2.3

テーブルには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という別の変数を作成することです。この値は、NPV < 4とDistancia> 12とCura [i-1]という条件が満たされたときに最初の異なるNUMDCREDが現れるときに1に設定され、 1]!= 1に達する。 P.Morosoの値は、条件に達すると変化するまで、各レコードにそれを保持する必要があります。これは、最初のNUMDCREDがP.Morosoの値が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 

瞬間イムのためにこれを行うには、次のような単純な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 programming :How to speed up a loop that takes 2 hours and the reasons why it takes a lot

+0

NUMDCRED == 0002の出力を得るには、NPV <= 4ではなくNPV <= 4を意味しますか? – rawr

答えて

2

あなたは必要ありませんが、あなたが機能

f <- function(data) 
    cumsum(with(data, Distancia > 12 & NPV <= 4 & c(0, CURA[-length(CURA)]) != 1)) + 1L 

にあなたのロジックを記述し、データのサブセットに適用することができますベースで

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 ') 

ループ

ex$P.Moroso2 <- unlist(by(ex, dd$NUMDCRED, f)) 

identical(ex$P.Moroso, ex$P.Moroso2) 
# [1] TRUE 

データに翻訳されています。テーブル

+1

data.tablishでは、その構文が好きな人は、 'c(0、CURA [-length(CURA)])'は 'shift(CURA、fill = 0)'だと思います。また、 'DT [、f(.SD)、by = g]'は、いくつかのほうが必要なときに( ''遅くなる可能性があるので) '.SD'のすべての列をロードするので、 – Frank

+0

@フランクありがとう、もし私がそれを台無しに編集してください – rawr

+0

私はちょうど解決策を試して、それはうまくいくようです。私は解決策をテストして、答えが得られた後に欠けているものがないかどうかを確認する必要があります。助けてくれてありがとう。 – Anflores

0

このような意味ですか...?

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 
+0

私がやっていたことは、遅いためにforループの使用を避けることでした。 – Anflores

-1

私は高速なソリューションを持っていると思うが、私はそれをテストしていないので、私は本当に知りません。ここに私の思考プロセスは次のとおりです。

  1. P.Morosoの値は常に1で変更をNUMDCREDたびに起動するので、あなたは最初、NUMDCREDの値でデータを分割することができます。データの各サブセットをリストに入れます。

  2. lapplyを使用して関数をリストの各データセットに適用できるようになりました。最初に、指定した条件が満たされている場合はTRUE、条件が指定されていない場合はFALSEの列を作成します。次に、この列の累積合計をとり、これをP.Moroso列として保管することができます。私はそれがあなたが望むものでなければならないと思う。

  3. すべてのデータセットをまとめて結合します。

関連する問題