をベクトルでない-apply関数にforループの変換:各一意のIDに対して入力がデータフレームである私は、およそ次のようになります3列のデータ持っ
uid <- c(1,1,1,1,1,1,2,2,2)
sale <- c(0,1,1,0,0,0,0,1,0)
e <- as.data.frame(cbind(uid, sale))
e$uid <- as.factor(e$uid)
e$sincesale <- NA
を、私は同じ手順を適用したいです - 前回の販売からの日数を計算します。
これを行うことができるfor-loopを簡単に思い付くことができます。問題は、何百万行もあることです。したがって、この手順を完了するのに時間がかかります。 e$uid
にtapply
を使用しました。しかし、tapply
はベクトルを入力としてのみ受け入れます。
どのような代替方法(for-loopより高速です)を使用できますか?
私のforループ:
for (i in 2:length(e$uid)){
#working within the good with the same unique id (uid)
if (e$uid[i] == e$uid[i-1]){
if (e$sale[i]==1){
sincesale[i] <- sincesale[i-1]+1
}
if (e$sale[i]==0){
#if sale just ended, number of days since sale is 1
if (e$sale[i-1]==1){
e$sincesale[i] <- 1
}
#if sale ended a few periods ago add 1 to previous value of "sincesale"
if (e$sale[i-1] == 0){
e$sincesale[i] <- e$sincesale[i-1] + 1
}
}
}
}
UPD:
さて、私は正直、最後の夜と朝のために自分に取り組んでみましたが、新たな問題の解決策を考え出すことができませんでした。私は提案された方法を使ってみましたが、小さな問題の1つは、最初の行から "sincesale"を計算し始めるということです。(売上は最初から始まっていませんが、最初の行はtrueです。次の例では、入力は、forループ(「sincesale」)を用いた結果を生成し、提案dplyr(「sincesale4」)を使用して:
uid <- c(1,1,1,1,1,1,2,2,2,2,3,3,3,3,3,3,3,3,3,4,4,4)
sale <- c(0,0,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0)
e <- as.data.frame(cbind(uid, sale))
e$uid <- as.factor(e$uid)
uid sale first sincesale sincesale4
1 1 0 1 NA 0
2 1 0 1 NA 1
3 1 1 0 NA 1
4 1 0 0 1 2
5 1 0 0 2 3
6 1 0 0 3 4
7 2 0 1 NA 0
8 2 1 1 NA 0
9 2 0 0 1 1
10 2 1 0 NA 1
11 3 0 1 NA 0
12 3 0 1 NA 1
13 3 0 0 NA 2
14 3 0 0 NA 3
15 3 0 0 NA 4
16 3 0 0 NA 5
17 3 1 0 NA 5
18 3 1 0 NA 5
19 3 0 0 1 6
20 4 0 1 NA 0
21 4 0 1 NA 1
22 4 0 0 NA 2
ちょうど 'e < - data.frame(uid、sale); e $ uid < - as.factor(e $ uid); e $ sincesale < - NA'は私がそれをソートするべきだと信じています。 – thelatemail