我有来自两个代表同一组事件的数据集。并非所有事件都存在于两个集合中,一些事件具有多个事件,并且定时信息不一定是同步的。例如:考虑两个在X,Y中正确配准但具有不同灵敏度和响应特性的传感器,以及漂移时钟。
我可以执行数据帧的外连接并拆分complete.cases()。这会产生不匹配的事件和内部联接结果。由于两个集合中的多个事件在X,Y上发生碰撞,因此内部联接结果可能非常大。我相信这被称为错误指定的连接,但它提供了我可以进一步过滤以匹配事件的结果。
我尝试在键上获取unique(),使用subset()进行提取并有条件地处理。如果子集的nrows()为1,则它是推定匹配,如果nrows()大于1,我会进行进一步处理以匹配我能做的事情。我试过在键上做一个split(),它更快,但它也有更大的数据集的问题。
使用data.table似乎可以加快速度,但不会太多。但是,我确信我没有使用它的完整功能。此时我所做的只是指定键,因此不需要为merge()重新生成它们。
以下是我想采取的一些措施来加快速度:
以下是生成几个代表性数据框的代码:
# Describe the basic frame
seedSize <- 7
keyCols <- c("x", "y")
noKeyCols <- c("time", "duration")
colSize <- length(keyCols) + length(noKeyCols)
frameSize <- seedSize * colSize
# Instantiate two with unique values
DF1 <- data.frame(matrix(1:frameSize, nrow=seedSize, ncol=colSize))
colnames(DF1) <- append(keyCols, noKeyCols)
DF2 <- DF1 + frameSize
# Duplicate a few from self and other and mangle no-key values
DF1 <- rbind(DF1, DF2[c(1:4, 1:3, 1, 6),])
DF1 <- rbind(DF1, DF1[c(1:5, 1:2),])
newRows <- (seedSize+1):nrow(DF1)
DF1[newRows, noKeyCols] <- DF1[newRows, noKeyCols] + newRows
DF2 <- rbind(DF2, DF1[c(1:4, 1:3, 1, 6),])
DF2 <- rbind(DF2, DF2[c(1:5, 1:2),])
newRows <- (seedSize+1):nrow(DF2)
DF2[newRows, noKeyCols] <- DF2[newRows, noKeyCols] + newRows
# Do some joins (sorting to make comparable)
DFI <- merge(DF1, DF2, by=keyCols)
DFI <- DFI[do.call(order, as.list(DFI),),]
row.names(DFI) <- NULL
DFO <- merge(DF1, DF2, by=keyCols, all=TRUE)
# Use complete.cases() to generate inner-join from outer
DFI2 <- DFO[complete.cases(DFO),]
row.names(DFI2) <- NULL
提前致谢。
答案 0 :(得分:0)
假设DT1
和DT2
是您的data.tables,我认为这是您正在寻找的(不确定):
setkey(DT1, x, y)
DT1[DT2, nomatch=0L]
如果您愿意,也可以将DT2
的密钥设置为x,y
。
答案 1 :(得分:0)
我认为编写一个在请求的表单中生成结果的合并会更高效,但我能够编写一些代码来将合并结果按到该表单中。请记住,对于Data.Table,必须设置 allow.cartesian = TRUE 以允许在键列中存在重复项时进行合并:
# Split out complete.cases
DF <- split(DFO, complete.cases(DFO))
DF.nomatch <- DF[["FALSE"]]
row.names(DF.nomatch) <- NULL
DF <- DF[["TRUE"]]
# Use aggregate to get frequency counts on keyCols
# to split out one-match cases
DF$Freq <- NA
DF.a <- aggregate(DF["Freq"], by=DF[,keyCols], length)
DF$Freq <- NULL
DF.a <- DF.a[DF.a$Freq==1, keyCols]
DF <- split(DF, do.call(paste, c(DF[keyCols], sep=".")) %in%
do.call(paste, c(DF.a[keyCols], sep=".")))
rm(DF.a)
DF.onematch <- DF[["TRUE"]]
row.names(DF.onematch) <- NULL
DF <- DF[["FALSE"]]
row.names(DF) <- NULL
# Collapse non-key columns so aggregate and unique can be used
combCols <- c(".x", ".y")
for (i in combCols) {
dcl <- append(list("c", SIMPLIFY=FALSE, USE.NAMES=FALSE),
as.list(DF[, paste0(noKeyCols, i)]))
DF[[i]] <- do.call(mapply, dcl)
}
# Remove columns which were collapsed
DF <- DF[, -which(names(DF) %in%
as.vector(outer(noKeyCols, combCols, paste0)))]
# Aggregate and generate unique non-key value lists
DF.a <- aggregate(DF[combCols], by=DF[keyCols], unique)
# DF.a is now a data frame with unique x.y values corresponding
# to multiple matches (although one of .x and .y can be singular)
# The .x column is the list of left contributions and .y is the right
# DF.onematch is all 1::1 matches; x.y is unique
# DF.nomatch is all unmatched (outer) records; x.y may not be unique