我的代码有效。但它很慢,我希望加快速度,这样我就可以扩展到几万个观测数据集。
我有两个数据框,其中一个我使用data.table包转换为data.table以进行快速查找和连接。当3个字段与第二个数据集中的记录匹配时,我想记录来自一个数据集的记录。
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上第二个表中的所有相应行匹配。在该示例中,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"))
答案 0 :(得分: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)))