どのインターネットには想像もつかな統合/加入データです。フレームR?
-
29-09-2019 - |
質問
例えば(い場合に最も代表的な例が):
N <- 1e6
d1 <- data.frame(x=sample(N,N), y1=rnorm(N))
d2 <- data.frame(x=sample(N,N), y2=rnorm(N))
これが私のこれまで:
d <- merge(d1,d2)
# 7.6 sec
library(plyr)
d <- join(d1,d2)
# 2.9 sec
library(data.table)
dt1 <- data.table(d1, key="x")
dt2 <- data.table(d2, key="x")
d <- data.frame( dt1[dt2,list(x,y1,y2=dt2$y2)] )
# 4.9 sec
library(sqldf)
sqldf()
sqldf("create index ix1 on d1(x)")
sqldf("create index ix2 on d2(x)")
d <- sqldf("select * from d1 inner join d2 on d1.x=d2.x")
sqldf()
# 17.4 sec
解決
試合のアプローチの作品がある場合において一意となるキーでのデータフレームの各キーの値に初めてとなります。がある場合は複製をデータフレームの試合および統合アプローチは同じではありません。試合はもちろん、高速で役立っているとはいえませんとしています。特になるように重複します。(続き後のコード)
DF1 = data.frame(a = c(1, 1, 2, 2), b = 1:4)
DF2 = data.frame(b = c(1, 2, 3, 3, 4), c = letters[1:5])
merge(DF1, DF2)
b a c
1 1 1 a
2 2 1 b
3 3 2 c
4 3 2 d
5 4 2 e
DF1$c = DF2$c[match(DF1$b, DF2$b)]
DF1$c
[1] a b c e
Levels: a b c d e
> DF1
a b c
1 1 1 a
2 1 2 b
3 2 3 c
4 2 4 e
のsqldfコード)に掲載された質問が表示されるコンフィデンス指数が使用される二つのテーブルですが、実際、もしくは付加されたテーブルが上書きされる前に、sql selectっ走ることになる部分を占めるのはなぜです。アsqldfのデータフレームおRセッションを構成するデータベース、テーブルsqlite.それぞれの時間のコードとは、無資格のテーブル名のようにおRワークスペースではなく、sqliteの主要なデータベースです。このようにselectステートがしたかったかを読み込みd1、d2のワークスペースにsqliteの主要なデータベースに気をつかうものがある。その結果と参加のないスを作成します。また、バージョンd1およびd2れたsqliteの主要なデータベースのように参照として主なものです。d1、主なものです。d2としてではなくd1、d2。また、行われているところであることを可能な限り速くしますのでご注意簡単に参加できなく使用上のインデックスの両方のテーブルで保存することができます時間を作るのにスを作成します。のコードを以下に示します。
その仕事を通知する精密に計算することで大きな違いるパッケージができます。例えば、私たちは、合併および合します。この結果はほぼ逆の。最初の例から最速を遅い以下になります。データです。テーブル、plyr、sqldfは次の例はsqldf,集計データです。テーブルplyr--近くの逆をつなぎ合わせます。最初の例ではsqldfが3xより遅くなデータです。テーブルとその200xよplyr100倍以上のデータです。表に示す。以下のコード入力、出力タイミングの統合の出力タイミングをしました。そも価値のあることsqldfに基づくデータベースやそのため対応できるオブジェによRで取扱いをご利用の場合dbname引数のsqldf)、その他の方法に限られる処理。もし絵sqldfとsqliteでにも対応しH2およびPostgreSQLデータベースです。
library(plyr)
library(data.table)
library(sqldf)
set.seed(123)
N <- 1e5
d1 <- data.frame(x=sample(N,N), y1=rnorm(N))
d2 <- data.frame(x=sample(N,N), y2=rnorm(N))
g1 <- sample(1:1000, N, replace = TRUE)
g2<- sample(1:1000, N, replace = TRUE)
d <- data.frame(d1, g1, g2)
library(rbenchmark)
benchmark(replications = 1, order = "elapsed",
merge = merge(d1, d2),
plyr = join(d1, d2),
data.table = {
dt1 <- data.table(d1, key = "x")
dt2 <- data.table(d2, key = "x")
data.frame( dt1[dt2,list(x,y1,y2=dt2$y2)] )
},
sqldf = sqldf(c("create index ix1 on d1(x)",
"select * from main.d1 join d2 using(x)"))
)
set.seed(123)
N <- 1e5
g1 <- sample(1:1000, N, replace = TRUE)
g2<- sample(1:1000, N, replace = TRUE)
d <- data.frame(x=sample(N,N), y=rnorm(N), g1, g2)
benchmark(replications = 1, order = "elapsed",
aggregate = aggregate(d[c("x", "y")], d[c("g1", "g2")], mean),
data.table = {
dt <- data.table(d, key = "g1,g2")
dt[, colMeans(cbind(x, y)), by = "g1,g2"]
},
plyr = ddply(d, .(g1, g2), summarise, avx = mean(x), avy=mean(y)),
sqldf = sqldf(c("create index ix on d(g1, g2)",
"select g1, g2, avg(x), avg(y) from main.d group by g1, g2"))
)
の出力からのベンチマーク電話との比較統合の計算には:
Joining by: x
test replications elapsed relative user.self sys.self user.child sys.child
3 data.table 1 0.34 1.000000 0.31 0.01 NA NA
2 plyr 1 0.44 1.294118 0.39 0.02 NA NA
1 merge 1 1.17 3.441176 1.10 0.04 NA NA
4 sqldf 1 3.34 9.823529 3.24 0.04 NA NA
の出力からのベンチマーク電話との比較に集計の計算には:
test replications elapsed relative user.self sys.self user.child sys.child
4 sqldf 1 2.81 1.000000 2.73 0.02 NA NA
1 aggregate 1 14.89 5.298932 14.89 0.00 NA NA
2 data.table 1 132.46 47.138790 131.70 0.08 NA NA
3 plyr 1 212.69 75.690391 211.57 0.56 NA NA
他のヒント
132秒はGaborの結果で報告されました data.table
実際にはベース関数のタイミングです colMeans
と cbind
(これらの関数を使用して誘導されるメモリの割り当てとコピー)。使用する良い方法と悪い方法があります data.table
, 、 それも。
benchmark(replications = 1, order = "elapsed",
aggregate = aggregate(d[c("x", "y")], d[c("g1", "g2")], mean),
data.tableBad = {
dt <- data.table(d, key = "g1,g2")
dt[, colMeans(cbind(x, y)), by = "g1,g2"]
},
data.tableGood = {
dt <- data.table(d, key = "g1,g2")
dt[, list(mean(x),mean(y)), by = "g1,g2"]
},
plyr = ddply(d, .(g1, g2), summarise, avx = mean(x), avy=mean(y)),
sqldf = sqldf(c("create index ix on d(g1, g2)",
"select g1, g2, avg(x), avg(y) from main.d group by g1, g2"))
)
test replications elapsed relative user.self sys.self
3 data.tableGood 1 0.15 1.000 0.16 0.00
5 sqldf 1 1.01 6.733 1.01 0.00
2 data.tableBad 1 1.63 10.867 1.61 0.01
1 aggregate 1 6.40 42.667 6.38 0.00
4 plyr 1 317.97 2119.800 265.12 51.05
packageVersion("data.table")
# [1] ‘1.8.2’
packageVersion("plyr")
# [1] ‘1.7.1’
packageVersion("sqldf")
# [1] ‘0.4.6.4’
R.version.string
# R version 2.15.1 (2012-06-22)
私はPlyrをよく知らないことに注意してくださいので、頼る前にHadleyに確認してください plyr
ここのタイミング。また、に注意してください data.table
変換する時間を含めてください data.table
そして、鍵を設定します。
この回答は、2010年12月に最初に回答されて以来更新されています。以前のベンチマークの結果は以下にあります。何が変わったかを確認するために、この答えの改訂履歴をご覧ください。
test replications elapsed relative user.self sys.self
4 data.tableBest 1 0.532 1.000000 0.488 0.020
7 sqldf 1 2.059 3.870301 2.041 0.008
3 data.tableBetter 1 9.580 18.007519 9.213 0.220
1 aggregate 1 14.864 27.939850 13.937 0.316
2 data.tableWorst 1 152.046 285.800752 150.173 0.556
6 plyrwithInternal 1 198.283 372.712406 189.391 7.665
5 plyr 1 225.726 424.296992 208.013 8.004
簡単なタスク(結合の両側の一意の値)の場合私は使用します match
:
system.time({
d <- d1
d$y2 <- d2$y2[match(d1$x,d2$x)]
})
マージよりもはるかに高速です(私のマシン上で0.13sから3.37s)。
私のタイミング:
merge
: :3.32splyr
: :0.84smatch
: :0.12s
ミックスにDPLYRを使用してベンチマークを投稿するのは面白いと思いました:(多くのことが実行されていました)
test replications elapsed relative user.self sys.self
5 dplyr 1 0.25 1.00 0.25 0.00
3 data.tableGood 1 0.28 1.12 0.27 0.00
6 sqldf 1 0.58 2.32 0.57 0.00
2 data.tableBad 1 1.10 4.40 1.09 0.01
1 aggregate 1 4.79 19.16 4.73 0.02
4 plyr 1 186.70 746.80 152.11 30.27
packageVersion("data.table")
[1] ‘1.8.10’
packageVersion("plyr")
[1] ‘1.8’
packageVersion("sqldf")
[1] ‘0.4.7’
packageVersion("dplyr")
[1] ‘0.1.2’
R.version.string
[1] "R version 3.0.2 (2013-09-25)"
追加しました:
dplyr = summarise(dt_dt, avx = mean(x), avy = mean(y))
DPLYRのデータをデータテーブルでセットアップします。
dt <- tbl_dt(d)
dt_dt <- group_by(dt, g1, g2)
更新しました: data.tablebadとplyrを削除しましたが、Rstudio Open(i7、16GB RAM)に他なりません。
data.table 1.9およびdplyrを使用して、データフレームを使用してください。
test replications elapsed relative user.self sys.self
2 data.tableGood 1 0.02 1.0 0.02 0.00
3 dplyr 1 0.04 2.0 0.04 0.00
4 sqldf 1 0.46 23.0 0.46 0.00
1 aggregate 1 6.11 305.5 6.10 0.02
data.table 1.9およびdplyrを使用してデータテーブルを使用してください。
test replications elapsed relative user.self sys.self
2 data.tableGood 1 0.02 1 0.02 0.00
3 dplyr 1 0.02 1 0.02 0.00
4 sqldf 1 0.44 22 0.43 0.02
1 aggregate 1 6.14 307 6.10 0.01
packageVersion("data.table")
[1] '1.9.0'
packageVersion("dplyr")
[1] '0.1.2'
一貫性については、データテーブルを使用して、すべてとデータテーブル1.9とdplyrを備えたオリジナルです。
test replications elapsed relative user.self sys.self
5 dplyr 1 0.01 1 0.02 0.00
3 data.tableGood 1 0.02 2 0.01 0.00
6 sqldf 1 0.47 47 0.46 0.00
1 aggregate 1 6.16 616 6.16 0.00
2 data.tableBad 1 15.45 1545 15.38 0.01
4 plyr 1 110.23 11023 90.46 19.52
このデータは新しいdata.tableとdplyrには小さすぎると思います:)
より大きなデータセット:
N <- 1e8
g1 <- sample(1:50000, N, replace = TRUE)
g2<- sample(1:50000, N, replace = TRUE)
d <- data.frame(x=sample(N,N), y=rnorm(N), g1, g2)
ベンチマークを実行する前に、データを保持するためだけに約10〜13GBのRAMを取りました。
結果:
test replications elapsed relative user.self sys.self
1 dplyr 1 14.88 1 6.24 7.52
2 data.tableGood 1 28.41 1 18.55 9.4
10億を試しましたが、ラムを爆破しました。 32GBは問題ありません。
Arunによる編集](Dotcomken、このコードを実行してベンチマークの結果を貼り付けてください。ありがとう)。
require(data.table)
require(dplyr)
require(rbenchmark)
N <- 1e8
g1 <- sample(1:50000, N, replace = TRUE)
g2 <- sample(1:50000, N, replace = TRUE)
d <- data.frame(x=sample(N,N), y=rnorm(N), g1, g2)
benchmark(replications = 5, order = "elapsed",
data.table = {
dt <- as.data.table(d)
dt[, lapply(.SD, mean), by = "g1,g2"]
},
dplyr_DF = d %.% group_by(g1, g2) %.% summarise(avx = mean(x), avy=mean(y))
)
ここでのArunの要求に従って、あなたが私に提供してくれたものの出力を実行するために:
test replications elapsed relative user.self sys.self
1 data.table 5 15.35 1.00 13.77 1.57
2 dplyr_DF 5 137.84 8.98 136.31 1.44
混乱して申し訳ありませんが、深夜が私に届きました。
データフレームでDPLYRを使用することは、要約を処理する効率が低い方法であるようです。これにより、データの正確な機能を比較する方法はありますか。 Group_byまたはData.Tableを作成する前に、ほとんどのデータをクリーニングする必要があるため、私はほとんど分離したいと思います。好みの問題かもしれませんが、最も重要な部分は、データをどれだけ効率的にモデル化できるかだと思います。
マージ関数とそのオプションのパラメーターを使用して:
内側の結合:Merge(DF1、DF2)はこれらの例で機能します。Rは一般的な変数名でフレームを自動的に結合するため、Merge(DF1、DF2、 "CustomerID")を指定して、あなたが確認することを確認することをお勧めします。あなたが望むフィールドのみに一致していました。一致する変数が異なるデータフレームに異なる名前を持っている場合、by.xおよびby.yパラメーターを使用することもできます。
Outer join: merge(x = df1, y = df2, by = "CustomerId", all = TRUE)
Left outer: merge(x = df1, y = df2, by = "CustomerId", all.x = TRUE)
Right outer: merge(x = df1, y = df2, by = "CustomerId", all.y = TRUE)
Cross join: merge(x = df1, y = df2, by = NULL)