rbind
それぞれがメモリ内にデータフレームの新しいコピーを作成するため、rbinding はこれには適していません。コードをより簡潔にするためだけにループを使用して、ほとんどベクトル化されたアプローチを使用すると、より迅速に答えを得ることができます。非効率性を認識し、解決策を探すためのOPへの小道具。
注: 次の解決策は、任意の数の顧客に対して機能しますが、より多くのラグ列を使用するには若干の変更が必要です。
セットアップ: まず、使用するデータを生成する必要があります。次のように、それぞれ数週間のトランザクション データを持つ 2 人の異なる顧客を使用します。
data <- read.table(text="
transaction customer week amount
12551 cOne 32 1.32
12552 cOne 34 1.34
12553 cTwo 34 2.34
12554 cTwo 35 2.35
12555 cOne 36 1.36
12556 cTwo 37 1.37
", header=TRUE)
ステップ 1: いくつかの変数を計算し、新しいデータ フレームを初期化します。プログラミングを本当に簡単にするために、まず 2 つのことを知りたいと思います: 顧客数と週数です。これらの答えを次のように計算します。
customer_list <- unique(data$customer)
# cOne cTwo
week_span <- min(data$week):max(data$week)
# 32 33 34 35 36 37
次に、計算した変数に基づいて新しいデータ フレームを初期化する必要があります。この新しいデータ フレームでは、データ内の週だけでなく、毎週のエントリが必要です。ここで、「week_span」変数が役に立ちます。
new_data <- data.frame(
week=sort(rep(week_span,length(customer_list))),
customer=customer_list,
activity_last_week=NA,
activity_2_weeks_ago=NA)
# week customer activity_last_week activity_2_weeks_ago
# 1 32 cOne NA NA
# 2 32 cTwo NA NA
# 3 33 cOne NA NA
# 4 33 cTwo NA NA
# 5 34 cOne NA NA
# 6 34 cTwo NA NA
# 7 35 cOne NA NA
# 8 35 cTwo NA NA
# 9 36 cOne NA NA
# 10 36 cTwo NA NA
# 11 37 cOne NA NA
# 12 37 cTwo NA NA
顧客ごとに週のリストを繰り返してソートしていることに気付くでしょう。そのため、1,1,2,2,3,3,4,4...n,n に似たリストが得られ、繰り返し回数は次のようになります。データ内の顧客数。これにより、「顧客」データを単なる顧客のリストとして指定できます。これは、リストがスペースを埋めるために繰り返されるためです。ラグ列は今のところ NA のままです。
ステップ 2: ラグ値を入力します。さて、物事は非常に単純です。各顧客の行のサブセットを取得し、毎週取引があったかどうかを調べるだけです。これを行うには、「一致」関数を使用して毎週の値を引き出します。データが存在しない場合、NA 値を取得し、それらをゼロに置き換える必要があります (アクティビティがない場合はトランザクションがゼロであると仮定します)。次に、遅延列については、遅延している週数に応じて NA で値をオフセットします。
# Loop through the customers.
for (i in 1:length(customer_list)){
# Select the next customer's data.
subset <- data[data$customer==customer_list[i],]
# Extract the data values for each week.
subset_amounts <- subset$amount[match(week_span, subset$week)]
# Replace NA with zero.
subset_amounts <- ifelse(is.na(subset_amounts),0,subset_amounts)
# Loop through the lag columns.
for (lag in 1:2){
# Write in the data values with the appropriate
# number of offsets according to the lag.
# Truncate the extra values.
new_data[new_data$customer==customer_list[i], (2+lag)] <- c(rep(NA,lag), subset_amounts[1:(length(subset_amounts)-lag)])
}
}
# week customer activity_last_week activity_2_weeks_ago
# 1 32 cOne NA NA
# 2 32 cTwo NA NA
# 3 33 cOne 1.32 NA
# 4 33 cTwo 0.00 NA
# 5 34 cOne 0.00 1.32
# 6 34 cTwo 0.00 0.00
# 7 35 cOne 1.34 0.00
# 8 35 cTwo 2.34 0.00
# 9 36 cOne 0.00 1.34
# 10 36 cTwo 2.35 2.34
# 11 37 cOne 1.36 0.00
# 12 37 cTwo 0.00 2.35
他の状況では...行が欠落していない順序付けられた一連の時間データがある場合、この種のタスクは「埋め込み」機能を使用すると非常に簡単になります。次のようなデータがあるとします。
data <- data.frame(week=1:20, value=1:20+(1:20/100))
# week value
# 1 1 1.01
# 2 2 2.02
# 3 3 3.03
# 4 4 4.04
# 5 5 5.05
# 6 6 6.06
# 7 7 7.07
# 8 8 8.08
# 9 9 9.09
# 10 10 10.10
# 11 11 11.11
# 12 12 12.12
# 13 13 13.13
# 14 14 14.14
# 15 15 15.15
# 16 16 16.16
# 17 17 17.17
# 18 18 18.18
# 19 19 19.19
# 20 20 20.20
次のように、遅延データセットをすぐに作成できます。
new_data <- data.frame(week=data$week[3:20], embed(data$value,3))
names(new_data)[2:4] <- c("this_week", "last_week", "2_weeks_ago")
# week this_week last_week 2_weeks_ago
# 1 3 3.03 2.02 1.01
# 2 4 4.04 3.03 2.02
# 3 5 5.05 4.04 3.03
# 4 6 6.06 5.05 4.04
# 5 7 7.07 6.06 5.05
# 6 8 8.08 7.07 6.06
# 7 9 9.09 8.08 7.07
# 8 10 10.10 9.09 8.08
# 9 11 11.11 10.10 9.09
# 10 12 12.12 11.11 10.10
# 11 13 13.13 12.12 11.11
# 12 14 14.14 13.13 12.12
# 13 15 15.15 14.14 13.13
# 14 16 16.16 15.15 14.14
# 15 17 17.17 16.16 15.15
# 16 18 18.18 17.17 16.16
# 17 19 19.19 18.18 17.17
# 18 20 20.20 19.19 18.18