2017-01-03 11 views
7

私はdata.tableに日付、郵便番号、および購入金額を記載しています。別の列とグループの値に基づいて新しいdata.table列を作成する

library(data.table) 
set.seed(88) 
DT <- data.table(date = Sys.Date()-365 + sort(sample(1:100, 10)), 
zip = sample(c("2000", "1150", "3000"),10, replace = TRUE), 
purchaseAmount = sample(1:20, 10)) 

これは、次のように作成されます。

date  zip    purchaseAmount 
1: 2016-01-08 1150    5 
2: 2016-01-15 3000    15 
3: 2016-02-15 1150    16 
4: 2016-02-20 2000    18 
5: 2016-03-07 2000    19 
6: 2016-03-15 2000    11 
7: 2016-03-17 2000    6 
8: 2016-04-02 1150    17 
9: 2016-04-08 3000    7 
10: 2016-04-09 3000    20 

私は4列目earlierPurchasesを追加したいと思います。この列は、前のxdatezipcodeの中のpurchaseAmountのすべての値がsumである必要があります。

EDIT:フランクからの提案を1として、ここで予想される出力です:

  date zip purchaseAmount new_col 
1: 2016-01-08 1150    5  5 
2: 2016-01-15 3000    15  15 
3: 2016-02-15 1150    16  16 
4: 2016-02-20 2000    18  18 
5: 2016-03-07 2000    19  19 
6: 2016-03-15 2000    11  30 
7: 2016-03-17 2000    6  36 
8: 2016-04-02 1150    17  17 
9: 2016-04-08 3000    7  7 
10: 2016-04-09 3000    20  27 

これを行うにはdata.table方法はありますか、私はちょうどループfunctionを書くべきですか?

+2

下記のコメントを参考にしてください。これは入力と予想出力の両方を送信することを推奨しているため、単に質問を読むことで回答が希望の結果を達成するかどうかは明らかです。ここにいくつかのガイダンスがあります:http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/28481250#28481250それを編集するのは遅すぎることはありません。 – Frank

+1

ガイダンスとコードを編集していただきありがとうございます@フランク。私は質問への出力を編集し、ビネットを読んで、あなたの解決策をよりよく理解するでしょう。これがフォーラムの最初の質問だったので、あなたは答えと提案を提供した丁寧で有益な方法を本当に感謝します。 – Mantelimies

答えて

11

これは動作するようです:

DT[, new_col := 
    DT[.(zip = zip, d0 = date - 10, d1 = date), on=.(zip, date >= d0, date <= d1), 
    sum(purchaseAmount) 
    , by=.EACHI ]$V1 
] 


      date zip purchaseAmount new_col 
1: 2016-01-08 1150    5  5 
2: 2016-01-15 3000    15  15 
3: 2016-02-15 1150    16  16 
4: 2016-02-20 2000    18  18 
5: 2016-03-07 2000    19  19 
6: 2016-03-15 2000    11  30 
7: 2016-03-17 2000    6  36 
8: 2016-04-02 1150    17  17 
9: 2016-04-08 3000    7  7 
10: 2016-04-09 3000    20  27 

は、これが効果的に各行を取って、「非エクイ」に参加使用しています。各行について式on=の条件を満たすすべての行を検索します。行(by=.EACHI)で合計します。この場合、非等価結合は、おそらく、いくつかの積和法よりも効率が悪いでしょう。


どのように動作しますか?

data.tableに列を追加するには、通常の構文はDT[, new_col := expression]です。ここで、式は実際にはDT[...]の外部でも機能します。自分自身でそれを実行してみてください:

DT[.(zip = zip, d0 = date - 10, d1 = date), on=.(zip, date >= d0, date <= d1), 
    sum(purchaseAmount) 
, by=.EACHI ]$V1 

それだけで参加されるまであなたが徐々に開き、ドキュメントのページに記載されているように

DT[.(zip = zip, d0 = date - 10, d1 = date), on=.(zip, date >= d0, date <= d1), 
    sum(purchaseAmount) 
, by=.EACHI ] 
# note that V1 is the default name for computed columns 

DT[.(zip = zip, d0 = date - 10, d1 = date), on=.(zip, date >= d0, date <= d1)] 
# now we're down to just the join 

結合構文は、x[i, on=.(xcol = icol, xcol2 < icol2)]のようなものです...これを簡素化することができますdata.tableパッケージがロードされた状態で?data.tableとRコンソールを入力します。

data.tableを開始するには、the vignettesを確認することをおすすめします。その後、これはおそらくもっと見やすく見えるでしょう。

+0

答えをありがとう。しかし、結果は私が探しているものではありません。 6行目の 'new_col'の値は30(11 + 19)でなければならず、5行目では19でなければなりません。これは前の10行の' zip'に他の購入がないので最初の4行にも当てはまります日々。残念ながら、私は初心者であるため、コードを使って何をしたのかをすぐに理解することはできません。したがって、あなたが書いた内容を変更して解決策を提示することはできません。 – Mantelimies

+0

追加情報ありがとうございました。私は編集しましたが、その2つの行にもマッチすることがわかりました(残念ながら、コードはより複雑になりました)。 – Frank

-1

私は、これは私もそれを得た方法で、任意のdata.table解決策を見つけることができませんでした:

library(dplyr) 
earlierPurchases <- vector() 

for(i in 1:nrow(DT)) { 
    temp <- dplyr::filter(DT, zip == zip[i] & date < date[i]) 
    earlierPurchases[i] <- sum(temp$purchaseAmount) 
} 

DT <- cbind(DT, earlierPurchases) 

それは非常に高速に働きました。

+1

@フランク、あなたは正しいです、私は何が起こったのかわかりません、その瞬間に、それをキャッチするためにありがとう –

関連する問題