0

次の構造のデータフレームにデータがあります

transaction | customer | week | amount
12551       | ieeamo   | 32   | €23.54
12553       | ieeamo   | 33   | €17.00

次の構造で取得したいと思います(すべての週)

week | customer | activity last week | activity 2 weeks ago
32   | ieeamo   | €0.00              | €0.00
33   | ieeamo   | €23.54             | €0.00
34   | ieeamo   | €17.00             | €23.54             
35   | ieeamo   | €0.00              | €17.00 

基本的に、トランザクション データを相対データに変換しようとしています。

私の考えでは、これを行う最善の方法は、ループを使用して多くのデータフレームを生成し、最後にそれらすべてを rbind することです。ただし、このアプローチは効率的ではないようで、使用しているデータに合わせて拡張できるかどうかはわかりません。

より適切な解決策はありますか?

4

1 に答える 1

1

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
于 2013-08-14T17:22:53.660 に答える