在 R 中找到最近的行
finding nearest rows with apply in R
我正在尝试使此功能 运行 更快。理想情况下,我只需要 运行 之类的东西应用于数据框,并让它比我目前拥有的更快地吐出结果。该函数的作用是采用如下所示的数据框
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
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)}
嗯...你有 O(N2) 算法。这样做怎么样:
- 添加 index/ID 列
df$ID <- seq.int(nrow(df))
(O(N))
- 使用稳定排序将
df
按 Var1
排序 (O(N log(N)))
- 对列进行差分的一次线性传递,构建逻辑向量 (O(N))
- 从 ID 列获取索引 (O(N))
Var2
相同
然后你可以做结果的交集
假设您只处理两列并且两列都是整数,您可以使用 dist
和欧氏距离计算每个点之间的实际距离。然后你可以过滤那些更大的距离 2^0.5.
如果您使用整数,它会起作用,因为如果 var1 或 var2 中的距离为 2 或更大,您想要丢弃它,但在任何这些情况下,它总是 >= 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
我正在尝试使此功能 运行 更快。理想情况下,我只需要 运行 之类的东西应用于数据框,并让它比我目前拥有的更快地吐出结果。该函数的作用是采用如下所示的数据框
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
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)}
嗯...你有 O(N2) 算法。这样做怎么样:
- 添加 index/ID 列
df$ID <- seq.int(nrow(df))
(O(N)) - 使用稳定排序将
df
按Var1
排序 (O(N log(N))) - 对列进行差分的一次线性传递,构建逻辑向量 (O(N))
- 从 ID 列获取索引 (O(N))
Var2
然后你可以做结果的交集
假设您只处理两列并且两列都是整数,您可以使用 dist
和欧氏距离计算每个点之间的实际距离。然后你可以过滤那些更大的距离 2^0.5.
如果您使用整数,它会起作用,因为如果 var1 或 var2 中的距离为 2 或更大,您想要丢弃它,但在任何这些情况下,它总是 >= 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