2

動作するコードがあります。しかし、それは遅く、私はそれをスピードアップして、数-00,000の観測のデータセットにスケールアップできるようにしたいと思っています。

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はおそらく2倍になります。

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

たぶん誰かが私のコードのどの部分が最悪/最も遅いかを教えてくれるでしょう。私はそれが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)
}

アップデート

データの大まかな内容は次のとおりです。(明らかに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"))
4

1 に答える 1

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)))
于 2012-04-24T01:44:03.847 に答える