2

大丈夫。この質問を大幅に編集して、a)より意味のあるものにし、b)問題のどこにいるかを反映しました。

私は 2 つのデータ セットを持っています。それらを set1 と set2 と呼びましょう。それぞれ約 600 万行です。現在、data.tables として R にロードしています。

>set1<-data.table(read.csv('~/file1.csv', stringsAsFactors=F))
>setkey(set1, id1)
>head(set1)
     id1 start_unixtime end_unixtime seconds_diff        id2
1:  1674     1354741858   1354741858            0  227167461
2:  1674     1354752386   1354752951          565  227246263
3:  1674     1354764412   1354764412            0  227358796
4:  1674     1354773044   1354773776          732  227421295
5:  1674     1354778651   1354778651            0  227448774
6:  1674     1354810424   1354810424            0  227631113
>set2<-data.table(read.csv('~/file2.csv', stringsAsFactors=F))
>setkey(set2, id1)
>head(set2)
     id1    unix_timestamp event_name
1:  1674    1355202784           join
2:  1674    1354351118           join
3:  1674    1354349648           play
4:  1674    1354780517           join
5:  1674    1355278891           join
6:  1674    1354617262           join

指摘すべき問題点の 1 つ: set2 には一意のキーがありません。各行のタプルのみが実際に一意です。set1 では、id2 は一意です。楽しい時間!

私が実行している操作は次のようになります: のすべての行について、unix_timestamp を取得し、 whereと id1 が一致set2する行を見つけて、対応するを の適切な行に割り当てる必要があります。のすべての行にのエントリがありますが、 のすべての行に のエントリがあるわけではありません。の多くの行に1 つを割り当てることができます。私が最終的に必要とするのはこれです(注:私はまだ実際の成功を収めることができていないため、次のデータは偽物です.):set1start_unixtimestamp <= unix_timestamp <= end_unixtimestampset1.id2set2set2set1set1set2id2set2

>head(set2)
     id1    unix_timestamp event_name         id2
1:  1674        1355202784       join   227167461
2:  1674        1354351118       join   227157309
3:  1674        1354349648       play   227157309
4:  1674        1354780517       join   227157309
5:  1674        1355278891       join   271089456
6:  1674        1354617262       join   221729485

これが私が作ったデータテーブルの混乱です:

set2[, id2 := set1[set2[, id1], list(start_unixtime, end_unixtime, id2)][(start_unixtime <= unix_timestamp & unix_timestamp <= end_unixtime), id2, by=id2]][, list(id2)][, id2:= id2]

何が起こっていると私が理解しているかについて話すために:

  1. set2代入演算子を呼び出します:=
  2. 右側はset2 の id1 行からset1始まる を呼び出します。joining
  3. start_unixtimeend_unixtime、およびid2が選択されています。
  4. その結果から、2 番目の選択セットが実行され、 がとの間にid2ある場所が取得されます。utc_timestampid2start_unixtimeend_unixtime
  5. ...そしてここで、何かひどく間違ったことをしていると思います。なぜなら、このステップでは、常に 2 つの列があり、それぞれにラベルが付けられid2、同じ結果が含まれているように見えるからです。だから、私は1つの列を選択します...
  6. ...そして割り当て用に指定します。(なぜこれが2回行われるのかわかりません。この秒を使用するこのSO投稿と、使用しないこのSO投稿を見つけましたが、理由がまったくわかりませ:=

...これは機能しません。@mnel は次のような提案をしています。

set2[set1, nomatch=0][unix_timestamp %between c(start_unixtime, end_unixtime, incbounds=T)]

...彼のテストデータで試してみるとうまくいきますが、私のデータではうまくいきません。私のデータは、data.table適切に強制されていないタイプ (文字?) (または R ピリオド) である可能性がありますか? 私は密集しているかもしれませんが、as.integer()a の指定された列を呼び出す方法がわかりませんdata.table

編集data.table:ええ、私のデータはすべて文字でしたdata.frame。だから、set1$start_unixtime <- as.integer($set1$start_unixtime)少なくとも、すべてがすべて整数であると確信しています。ただし、そのコマンドを実行すると、次のようになります。

>head(set2)
Empty data.table (0 rows) of 8 cols: id1,utc_timestamp,event_name,start_unixtime,end_unixtime,seconds_diff...

追加 ここに私の実際のデータのスニペットがあります:

set1 <-  as.data.table(list(id1 = c(1674L, 1674L, 1674L, 1674L, 1674L, 1674L), 
     start_unixtime = c(1354741858L, 1354752386L, 1354764412L, 1354773044L, 1354778651L, 1354810424L), 
     end_unixtime = c(1354741858L, 1354752951L, 1354764412L, 1354773776L, 1354778651L, 1354810424L), 
    seconds_diff = c(0L, 565L, 0L, 732L, 0L, 0L), 
    id2 = c(227167461L, 227246263L, 227358796L, 227421295L, 227448774L, 227631113L))
set2 <- as.data.table(list(
    id1 = c(1674L, 1674L, 1674L, 1674L, 1674L, 1674L), 
    utc_timestamp = c(1354752431L, 1354780517L, 1354811978L, 1354824385L, 1354833271L, 1354862753L), 
    event_name = c("joinRegularTable_2", "joinRegularTable_2", "joinRegularTable_2", "joinRegularTable_2","joinRegularTable_2", "joinRegularTable_2"))
4

1 に答える 1

3

おそらくより完全な例を投稿する必要があるため、これがあなたのデータで機能するかどうかはわかりませんが、次のようなものが機能する可能性があります。1 つの結合 (バイナリ検索) と 1 つのベクトル スキャン (舞台裏で長い論理ベクトルをいくつか作成するため、理想的ではありません) を実行します。

もう少し複製を加えた、シンプルだがより大きなサンプル データ セットを提供しました。

DT <- as.data.table(list(id1 = c(5L, 1L, 5L, 1L, 5L, 3L, 5L, 3L, 1L, 3L), 
    id2 = 1:10, startunix = 1:10, endunix = 5:14))

DA <- as.data.table(list(id1 = c(3L, 5L, 5L, 5L), unixtime = c(5L, 1L, 6L, 12L)))

setkey(DA,id1)
setkey(DT,id1)


DT[DA, nomatch=0][unixtime %between% c(startunix, endunix)]

   id1 id2 startunix endunix unixtime
1:   5   1         1       5        6
2:   5   3         3       7        6
3:   5   5         5       9        6
4:   5   7         7      11        6

何をしているのかを説明すると、 でマッチングしてid1おりnomatch = 0、これらを含まないということです。これは、DA[J(5)] と DT[J(5)] の複数の行のすべての組み合わせに展開されます - この場合は

 DA[J(5)]
   id1 unixtime
1:   5        1
2:   5        6
3:   5       12
> DT[J(5)]
   id1 id2 startunix endunix
1:   5   1         1       5
2:   5   3         3       7
3:   5   5         5       9
4:   5   7         7      11

したがって、作成されたマージされたデータ セットには、12 の組み合わせすべてが含まれます。( 4 回 3)

次に、関数between(パッケージの一部) を使用して、との間のdata.table値をサブセット化します。unixtimestartunixendunix

私の知る限りでは、バイナリ検索を使用して何かが範囲内にあるかどうかを見つけることはできません (ただし、@MatthewDowle、メインdata.tableパッケージの作成者は SO でアクティブであり、これが可能または将来可能性が高い)

于 2012-12-18T01:53:41.237 に答える