2

我有有效的代码。但它很慢,我希望加快速度,这样我就可以扩大到包含 00,000 个观测值的数据集。

我有两个数据框,其中一个我使用 data.table 包转换为 data.table 以进行快速查找和连接。当 3 个字段与第二个数据集中的记录匹配时,我想记录一个数据集中的记录。

Original.df (data frame) 和 LookHereForMatches.dt (data.table with key on a1, a2, a3)。Original.df 将有 100,000 到 300,000 个观测值,而 LookHereForMatches.dt 可能是 2 倍。

我遍历 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)
}

更新

数据大致如下。(显然是 R 和 StackExchange 的新手。我会弄清楚如何使表格更漂亮并回来修复它。感谢@joran 修复我的表格。)这些表格是非常基本的东西。我只想从第一个表中找到每一行,并将其与第二个表中 a1、a2 和 a3 上的所有适当行匹配。在示例中,Original.df 的第一行应与 LookHereForMatches.dt 表中的第 1、2 和 3 行配对,返回 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 秒,匹配和 cbind 只需要 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 回答