R中最近邻匹配

时间:2015-02-13 00:23:41

标签: r matching nearest-neighbor

我有10,000个观察列表(数值)。我想使用最近邻匹配从这些观察中生成5,000个匹配对。我试图想出一种有效的方法来做到这一点。

我的计划是对它们进行排序,然后调用观察i和i + 1一对,i = 1,3,...,9999,但这似乎不是最佳的(取决于我如何排序)较低/较高的值将得到更接近的匹配。

有没有人对更好的方法有一些建议?

我检查了R包是否匹配。然而,这些都需要我指出一些我没有的治疗/控制变量。我只想根据它们的接近程度将数字列表匹配成对。

提前谢谢。

数据结构:c(0.732851696218165,-0.479344482931516,-0.139582120592376, 0.477291542874127,0.485648507877746,0.226366004586156)

它基本上是一个数字向量。

2 个答案:

答案 0 :(得分:0)

我的记忆由@Metrics刷新,并且在一个稍微不同的方向上跟踪原始索引,这是一个函数:

mypairs <- function(x) {
    require("plyr")
    np <- length(x)
    g <- expand.grid(x, x)
    names(g) <- c("valueA", "valueB")
    g$absDiff <- abs(g$valueB - g$valueA)
    g$ind1 <- rep(1:np, np)
    g$ind2 <- rep(1:np, each = np)
    g <- arrange(g, absDiff)
    # remove g$diff == 0
    g <- g[-which(g$absDiff == 0),]
    # now every other value is a duplicate
    dups <- as.logical(1:nrow(g)%%2)
    g <- g[dups,]
    return(g)
    }

tst <- mypairs(rnorm(3)); tst

给出了:

      valueA     valueB   absDiff ind1 ind2
4 -0.6813464 -0.5329252 0.1484212    3    2
6 -0.5329252  2.5917185 3.1246437    2    1
8 -0.6813464  2.5917185 3.2730649    3    1

ind1ind2是原始矢量中值的索引,可能是您感兴趣的。由于组合比需要的多,所以组合很慢(combn没有这个问题,但它并不容易跟踪原始索引)。我正在考虑如何加快速度,但目前正在填补空白。

答案 1 :(得分:0)

毫无疑问,你继续前进,但我在这里迷恋这个小逻辑问题以及如何加速它!这是一个改进的函数,对于长向量执行得更好。

mypairs <- function(x) {
    require("plyr")
    np <- length(x)
    M <- matrix(NA_real_, np, np)
    for (i in 1:np) {
        for (j in 1:np) { # compute only upper triangle
            if (j > i) M[i,j] <- x[j]-x[i]
            }
        }
    M <- abs(M)
    # unstack column by column
    d <- vector("numeric", np^2)
    for (i in 1:np) {
        d[(np*(i-1)+1):(np*i)] <- M[,i]
        }
    idx1 <- rep(1:np, np) # row index
    idx2 <- rep(1:np, each = np) # column index
    nope <- which(is.na(d))
    d <- d[-nope]
    idx1 <- idx1[-nope]
    idx2 <- idx2[-nope]
    df <- data.frame(dist = d, ptA = idx1, ptB = idx2)
    df <- arrange(df, d)
    df
    }

在我的旧Mac上我得到以下时间(n点,秒):1000,1.5; 2000年,6.4; 5000,45; 10000,213。还不错。最后使用数据表而不是数据框可能会节省一点时间。