【问题标题】:finding nearest rows with apply in R在R中使用apply查找最近的行
【发布时间】:2016-05-02 14:22:15
【问题描述】:

我试图让这个函数运行得更快。理想情况下,我会在数据帧上运行类似 apply 之类的东西,让它比我目前拥有的更快地吐出结果。这个函数的作用是它需要一个看起来像这样的数据框

df
   Var1 Var2
    5    0
    9    0
    4    1
    6    1
    2    2
    4    2

然后它遍历每一行并检查数据框中其他行的值(在 Var1 和 Var2 中)最接近您所在行中 Var1 和 Var2 的值。然后输出哪些行最接近其他行的列表。例如

myFunc(df)

[[1]]
[1] 3 4

[[2]]
integer(0)

[[3]]
[1] 1 6

[[4]]
[1] 1

[[5]]
integer(0)

[[6]]
[1] 3

因此,第 1 行的值最接近第 3 行和第 4 行,而第 2 行附近没有其他行。这是我的函数

myFunc = function(t) {
x=matrix(); x2=list()
y = matrix(); y2 = list()
for (i in 1:nrow(t)){
    for (j in 1:nrow(t)){
        #this will check for other rows <= 1 from the row I am currently in
        if (abs(t[i,1] - t[j,1]) <= 1) {
            x[j] = j
        } else { x[j] = NA }
        if (abs(t[i,2] - t[j,2]) <= 1) {
            y[j] = j
        } else { y[j] = NA }
    }
    x2[[i]] = x
    y2[[i]] = y
}
for (i in 1:length(x2)){
    x2[[i]] = x2[[i]][!x2[[i]] == i]
    y2[[i]] = y2[[i]][!y2[[i]] == i]
}
x2 = lapply(x2, function(x) x[!is.na(x)])
y2 = lapply(y2, function(x) x[!is.na(x)])

#this intersects Var1 and Var2 to find factors that are close to both Var1 and Var2
z = list()
for (i in 1:length(x2)){
    z[[i]] = intersect(unlist(x2[[i]]), unlist(y2[[i]]))
}
return(z)}

【问题讨论】:

  • 从您的代码看来,apply(as.matrix(dist(DF, "maximum")) == 1L, 2, which) 之类的内容可能会有所帮助?

标签: r apply


【解决方案1】:

假设您只使用两列和两列中的整数,您可以使用 dist 和欧几里德距离计算每个点之间的实际距离。然后你可以过滤那些距离更大的 2^0.5。

如果您使用整数,它会起作用,因为如果 var1 或 var2 中的距离为 2 或更大,您想丢弃它,但在任何这些情况下,它始终是 &gt;= 2

如果您不使用整数,您仍然可以使用dist,但单独处理每一列,然后过滤它们。

我在想这样的事情:

d1 <- dist(df$Var1) # or d1 <- dist(Var1)
d2 <- dist(df$Var2) # or d2 <- dist(Var2)

现在您可以过滤哪些小于 1

dF <- as.matrix(d1) <= 1 & as.matrix(d2) <= 1
diag(dF) <- NA

为了得到最终的结果,你可以

colnames(dF) <- NULL
dF2 <- lapply(as.data.frame(dF), which)
names(dF2) <- 1:nrow(df)

# dF2
# $`1`
# [1] 3 4

# $`2`
# integer(0)

# $`3`
# [1] 1 6

# $`4`
# [1] 1

# $`5`
# integer(0)

# $`6`
# [1] 3

【讨论】:

  • 这两列并不总是整数
  • 所以我尝试了您建议的 dist 功能,但它有时只能工作。我基本上得到了这个(示例),应该报告 TRUE,但我得到了 FALSE。 Var1 Var2 值 1 4 FALSE 1 5 FALSE
  • 当代码不起作用时,你能提供一个例子吗?我试过structure(list(Var1 = c(1, 1), Var2 = c(4, 5)), .Names = c("Var1", "Var2"), row.names = c(NA, -2L), class = "data.frame"),效果很好。使用dput以文本格式导出变量。
【解决方案2】:

嗯...你有 O(N2) 算法。这样做怎么样:

  • 添加索引/ID 列df$ID &lt;- seq.int(nrow(df)) (O(N))
  • 使用稳定排序将dfVar1 排序 (O(N log(N)))
  • 一个线性传递列做差异,构建逻辑向量 (O(N))
  • 从 ID 列获取索引 (O(N))

Var2 相同

然后你可以做你的结果交集

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多