【问题标题】:r - Classify matched and mismatched data from two setsr - 对两组匹配和不匹配的数据进行分类
【发布时间】:2014-12-20 19:26:13
【问题描述】:

我有来自两个来源的数据集,它们代表同一组事件。并非所有的事件都存在于两个集合中,有些事件有多次发生,时间信息不一定同步。例如:考虑两个传感器,它们在 X、Y 中正确注册,但具有不同的灵敏度和响应特性,以及漂移时钟。

我可以执行数据帧的外连接并拆分出 complete.cases()。这会产生不匹配的事件和内部连接结果。由于两个集合中的多个事件在 X、Y 上发生碰撞,内连接结果可能非常大。我相信这被称为错误指定的连接,但它给出的结果我可以进一步过滤以匹配事件。

我尝试在键上获取 unique(),使用 subset() 提取并有条件地处理。如果子集的 nrows() 为 1,则它是假定匹配,如果 nrows() 大于 1,我会进行进一步处理以匹配我所能匹配的。我试过在键上做一个 split(),它更快,但它也有更大的数据集的问题。

使用 data.table 似乎可以加快速度,但速度并不快。但是,我确信我没有使用它的全部功能。在这一点上,我所做的只是指定键,这样就不需要为 merge() 重新生成它们。

以下是我想做的一些事情来加快速度:

  1. 提取不匹配的事件,以便我可以进行内部联接而不是外部联接。
  2. 在进行任何基于键的拆分/子集之前拆分所有单匹配事件。
  3. 以具有 .x 值和另一个 .y 值的向量或列表而不是 .x 和 .y 的所有可能组合的形式获取多重匹配事件。

这里是生成几个有代表性的数据帧的代码:

# 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

提前致谢。

【问题讨论】:

    标签: r join split dataframe data.table


    【解决方案1】:

    假设 DT1DT2 是您的 data.tables,我认为这就是您正在寻找的(虽然不确定):

    setkey(DT1, x, y)
    DT1[DT2, nomatch=0L]
    

    如果您愿意,也可以将DT2 的密钥设置为x,y

    【讨论】:

    • 是的,对于我可怕的错误指定的连接,它必须是这样的:DT1[DT2, nomatch=0L, allow.cartesian=TRUE],这给出了一个内部连接。
    【解决方案2】:

    我相信编写一个在请求的表单中生成结果的合并会更高效,但是我能够编写一些代码来将合并结果按摩到该表单中。请记住,对于 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
    

    【讨论】:

      最近更新 更多