2017-07-12 2 views
2

私は約100万レコードと80カラムの大きなデータセットを持っています。処理を高速化するために、私はdata.tableを使用しています。今data.tableのインクリメントを伴う条件付きの作成

set.seed(1200) 
N_Blocks = 1348 
cyc=200 
City1 <- vector() 
City2 <- vector() 
a1 <- vector() 
a2 <- vector() 

for (a in 1:cyc) { 
City1 <- sample(paste("City", formatC(a, width=nchar(cyc), flag="0"), sep=""),N_Blocks,rep=T) 
a1 <- sample(0:1,N_Blocks,rep = T) 

City2 <- append(City2,City1) 
a2 <- append(a2,a1) 
} 

df1 <- data.frame(City2,a2) 

要件がためのことである:以下のサンプルデータのためのコードである私は、条件に基づいて新しい列を作成する必要があると私はdata.table

でこれを行う方法のよう失われています各都市(現在、このサンプルデータに200の都市があります)とa2 == 1の場合、12ヶ月で1秒の合計数を持つ新しい列を作成する必要があります。したがって、例えばCity001 & a2 == 1と1200のシードの場合、私は671のレコードを取得します。したがって、新しい列はコード01-12を持つ必要があります。したがって、a2 == 1の場合は1番目の56レコードはコード01、次の56のレコードのコード02の場合、.....最後の55レコードのCity001のa2 == 1の場合はコード12 671に追加)。 12ヶ月で各都市のa2の選択を分割するようなもの。

我々は、コマンドから選択の市レベルの概要を取得することができます -

table(df1$City2,df1$a2) 

我々は、この使用してdata.tableを達成することはできますか?

答えて

2

使用:

library(data.table) 
setDT(df1)[a2 == 1, mon := cut(seq_along(a2), 12, sprintf('%02d',1:12)), by = City2][] 

ができます:

  City2 a2 mon 
    1: City001 1 01 
    2: City001 1 01 
    3: City001 1 01 
    4: City001 1 01 
    5: City001 0 NA 
    ---    
269596: City200 1 12 
269597: City200 0 NA 
269598: City200 1 12 
269599: City200 1 12 
269600: City200 1 12 

これは何:data.frameはdata.tableに変換されsetDT(df1)

  • (それはまだdata.frameです)。
  • データはa2 == 1でフィルタリングされ、by = City2でグループ化されます。
  • 最後に、新しい列monが、選択された行の参照によって、cutで作成されます。 City2 -columnの各群について
  • cutは(seq_along(a2);これは1で始まり、GROUPSIZEで終了し、最初のグループのために、すなわち671)シーケンスを分割12(ほぼ)等しい部分に。各部分は対応するラベル(sprintf('%02d',1:12))を取得します。詳細は?cutを参照してください。

上記の方法の欠点は、最も少ないレコード数での区切りが最後ではないことです。その結果を要約によって示すことができるどの:

> df1[a2 == 1, .N, by = .(City2,mon)][1:24] 
     City2 mon N 
1: City001 01 56 
2: City001 02 56 
3: City001 03 56 
4: City001 04 56 
5: City001 05 56 
6: City001 06 56 
7: City001 07 55 
8: City001 08 56 
9: City001 09 56 
10: City001 10 56 
11: City001 11 56 
12: City001 12 56 
13: City002 01 56 
14: City002 02 55 
15: City002 03 56 
16: City002 04 55 
17: City002 05 56 
18: City002 06 55 
19: City002 07 55 
20: City002 08 56 
21: City002 09 55 
22: City002 10 56 
23: City002 11 55 
24: City002 12 56 

最後に、レコードの番号の小さい休憩を取得するには、使用することができます:

setDT(df1)[a2 == 1, mon := cut(seq_along(a2), 
           {n <- .N/12; 
           br <- c(0, rep(ceiling(n), round((n-floor(n))*12)), rep(floor(n), round((floor(n) - n + 1)*12))); 
           unique(c(cumsum(br),.N))}, 
           sprintf('%02d',1:12)), 
      by = City2][] 

数(12)の第1の解からのベクトルは、中括弧(01)の部分で別々にCity2の各グループについて計算されるブレークポイントのベクトルに置き換えられる)。この部分は、観測数が数ヶ月にわたりランダムに分布していないような方法でブレークを計算しますが、観測数の少ない月が常に最後になるようにブレークを計算します。上記explanantionに加え

、中括弧の間の部分は、以下のない:

  • まず各グループ(.N)の観測の数は12によって分割されています。しばしばこれは整数ではなく、小数点以下の値を持つ数値です。
  • rep(ceiling(n), round((n-floor(n))*12))は、第1のグループ(ceiling(n))の高い観測数を計算し、nの小数値によって決定される一定の回数をround((n-floor(n))*12)で繰り返す。
  • 小さいグループ(ブレーク)のグループサイズはrep(floor(n), round((floor(n) - n + 1)*12))で決まります。同様の方法です。 floor(n)はグループのサイズを決定し、round((floor(n) - n + 1)*12)は低いグループサイズに必要なグループの数を決定します。
  • 前の2つのベクトルは、開始ゼロ(c(0, rep ...))と一緒に置かれます。
  • cumsumを使って、0で始まり、末尾にグループサイズが追加されたベクトルが得られます(.N)。 uniqueにこれをラップすることで、一意のブレーク値が得られることを確認します。これは、nが完全に丸められた数(例えば、600/12の結果)である場合、最後の中断値がベクトルに2回現れるために必要とされる。

同じチェックが今、これが達成されていることを示しています

> df1[a2 == 1, .N, by = .(City2,mon)][1:24] 
     City2 mon N 
1: City001 01 56 
2: City001 02 56 
3: City001 03 56 
4: City001 04 56 
5: City001 05 56 
6: City001 06 56 
7: City001 07 56 
8: City001 08 56 
9: City001 09 56 
10: City001 10 56 
11: City001 11 56 
12: City001 12 55 
13: City002 01 56 
14: City002 02 56 
15: City002 03 56 
16: City002 04 56 
17: City002 05 56 
18: City002 06 56 
19: City002 07 55 
20: City002 08 55 
21: City002 09 55 
22: City002 10 55 
23: City002 11 55 
24: City002 12 55 
+0

私が正しくOPの質問を理解していれば、私は、まだそれは正しいですか分かりません。行669を例に取ってみると: '669:City001 1 07'、それは07ではなく12と言うべきです。City001行の最後の12番目の行(a2 = 1)はすべて12とラベル付けされるべきです。 – Mako212

+0

@ Mako212はい、それです正しい結果です。 'a2 == 0'の行は、OPの仕様に従って月の値を取得すべきではありません。 'df1 [1:669、sum(a2 == 0)]'を実行すると、 '326'が返されます。これは月の値を取得しない行の数です。 'a2 == 1'の行だけが月の値を取得するはずです。したがって、669 - 326 = 343行だけが月の値を取得する必要があります。つまり、行669の正しい結果は '07'です。 – Jaap

+0

@Jaap、ありがとうございます!これは動作します! {....}の中で何が起こっているのかちょっと詳しく説明できれば、多くの助けになります。非常に興味深いコードであり、理解しようとしていますが、それを得ることはできません。私のために行く長い道のり...... – user1412

関連する問題