2012-04-23 3 views
2

私は動作するコードを持っています。しかし、それは遅いです、そして私はそれをスピードアップしたいと思いますので、私は約2万回の観測データセットまでスケールアップすることができます。一致を見つけてdata.frameに追加する方法がより速くなりますか?

私は2つのデータフレームを持っています。そのうちの1つは、高速検索と結合のためにdata.tableパッケージを使用してdata.tableに変換します。 3つのフィールドが2番目のデータセットのレコードと一致すると、1つのデータセットからレコードを記録します。

Original.df(データフレーム)とLookHereForMatches.dt(キーがa1、a2、a3のdata.table)。 Original.dfは100,000〜300,000の観測値を持ち、LookHereForMatches.dtはおそらく2xになります。

私はOriginal.dfの各観測をループし、LookHereForMatches.dtで特定の基準に一致する観測値を探します。 LookHereForMatches.dtのいくつかのフィールドとOriginal.dfのいくつかのフィールドが必要です。私はサブセット()を使用して、必要な列だけを取得します。

誰かが私のコードのどの部分が最悪か/遅いかを教えてくれるかもしれません。私はそれがrbind(cbind())の部分だと信じなければならない。それが正しい方法だとは思われません。

matched_data.df <- data.frame() 
for(i in 1:nrow(Original.df)){ 
    a1 <- Original.df$col1 
    a2 <- Original.df$col2 
    a3 <- Original.df$col3 
    # Use data.table library "join" functionality to get matches (will find at least 1 and up to 4 matches, usually only 1 or 2) 
    match.df <- data.frame(LookHereForMatches.dt[J(a1, a2, a3)], stringsAsFactors=FALSE) 

    # combine matches with original data and add to data.frame to create big list of data with matches 
    matched_data.df <- rbind(cbind(match.df, Original.df[i,], stringsAsFactors=FALSE), matched_data.df) 
} 

ここでUPDATE

は、データがどのように見えるかを大まかにです。 (明らかにRとStackExchangeの初心者 テーブルをもっときれいにする方法を見つけ出し、それを修正するために戻ってきます。 テーブルを修正するための@joran。)テーブルはかなり基本的なものです。私は、最初のテーブルから各行を見つけて、それをa1、a2、およびa3の2番目のテーブルのすべての適切な行に一致させたいだけです。この例では、Original.dfの最初の行は、3行を返すLookHereForMatches.dtテーブルの行1,2、および3とペアにする必要があります。

Original.df <- read.table(textConnection(' 
a1 a2 a3 text.field numeric.field 
123 abc 2011-12-01 "some text" 1.0 
124 abc 2011-11-12 "some other text" 0.1 
125 bcd 2011-12-01 "more text" 1.2 
'), header=TRUE) 

LookHereForMatches.df <- read.table(textConnection(' 
a1 a2 a3 text.field numeric.field Status_Ind 
123 abc 2011-12-01 "some text" 10.5 0 
123 abc 2011-12-01 "different text" 0.1 1 
123 abc 2011-12-01 "more text" 0.1 1 
125 bcd 2011-12-01 "other text" 4.3 0 
125 bcd 2011-12-01 "text"  2.2 0 
'), header=TRUE) 

LookHereForMatches.dt <- data.table(LookHereForMatches.df, key=c("a1","a2","a3")) 
+1

は、あなたがより良い答えを得るでしょう、...私を許して。しかし条件付きのようなものをマッチさせることはできませんか? 'Origian.df [Origional.df $ a1%%LookHereForMatchers.dt $ a1&Origional.df $ a2%in%LookHereForMatches.dt $ a2、]'です。 'forループ'は遅いですが、 'rbind(cbind(...))'ははるかに遅いです。理想的には、割り当て前に 'matched_data.df'のフルサイズを割り当てることができます。もしあなたができないのであれば、私が上記のようなものを使っていくつかの助けになるはずです... – Justin

+0

なぜ、あなたは単にdata.tableの間で1つの結合をすることができないのですか? – joran

+0

サンプルデータを追加するように更新しました。 %で%を調べます。私はdata.tables間の結合を行うことはできません理由は...私はRの新人です。私も参加を検討します。 – user791770

答えて

3

それはあなたが探しているものでしょうmergeのように聞こえます。詳細は?mergeを参照してください。

> merge(Original.df, LookHereForMatches.df, by=c("a1","a2","a3")) 
    a1 a2   a3 text.field.x numeric.field.x text.field.y 
1 123 abc 2011-12-01 some text    1.0  some text 
2 123 abc 2011-12-01 some text    1.0 different text 
3 123 abc 2011-12-01 some text    1.0  more text 
4 125 bcd 2011-12-01 more text    1.2  other text 
5 125 bcd 2011-12-01 more text    1.2   text 
    numeric.field.y Status_Ind 
1   10.5   0 
2    0.1   1 
3    0.1   1 
4    4.3   0 
5    2.2   0 

あなたはより多くの制御をしたい場合、それは、舞台裏でこのような何かをmatchを使用します:

a <- with(Original.df, paste(a1, a2, a3, sep="\b")) 
b <- with(LookHereForMatches.df, paste(a1, a2, a3, sep="\b")) 
m <- match(b, a) 
cbind(Original.df[m,], LookHereForMatches.df) 

また、物事が両方に表示されないとき、それが何をするかを制御するallオプションを調べますデータセット。大規模なデータセットとスピードに関しては

merge(Original.df, LookHereForMatches.df, by=c("a1","a2","a3"), all=TRUE) 

(次のように)、あなたはそれぞれにdata.tableを使用してますが1E5および3E5の行でいくつかのスピードアップを得ることができ、私のシステムで、マージはわずか2.6秒と試合をとり、たった1.5秒です。私はあなたのデータがどのように見えるかわからないので、これが解決しない場合は、あなたのデータの小さなサンプルを提供できる場合

set.seed(5) 
N <- 1e5 
Original.df <- data.frame(a1=1:N, a2=1, a3=1, text1=paste("hi",1:N)) 
LookHereForMatches.df <- data.frame(a1=sample(1:N, 3*N, replace=TRUE), 
            a2=1, a3=1, text2=paste("hi", 1:(3*N))) 
+0

ありがとうございます。それでおしまい。接尾辞= c( "_ first"、 "_ second")またはこれに近いものは、命名にも役立ちます。それでも%で試してみてください。しかし、これはトリックを行うように見えます。私はそれをテストし、それがすべて正常に動作するようにするときにいくつかのタイミングの詳細を投稿します。 – user791770

+0

私はまだcbindが行を正しく一致させる方法を完全には明らかにしていませんが、merge()は私が必要とする場所に到達するので、それに固執します。 タイミング: original.dfの1,000行。 LookHereForMatches.df マージ()で3000行:0.015; forループ:3.1 10,000行; 30,000行 merge():0.25; forループ74秒。 – user791770