r - 不一致的 dist() foreach 结果
问题描述
我的数据大致采用以下格式,但非常大,但使用类和 uniqueId 变量按组分解。其中每个位置都是一对逐行 (x, y)。
df <-
data.frame(
x = c(1, 2, 3, 4, 5, 6, 8, 9, 10),
y = c(1, 2, 3, 4, 5, 6, 8, 9, 10),
class = c(0, 0, 0, 0, 0, 1, 0, 1, 0),
uniqueId = c("1-2-3", "1-2-3", "1-2-3", "1-2-4", "1-2-4", "1-2-4", "1-3-2", "1-3-2", "1-3-2"),
partialId = c("1.2", "1.2", "1.2", "1.2", "1.2", "1.2", "1.3", "1.3", 1.3")
)
我正在使用的函数应该通过数据框并计算到与当前行相同的 uniqueId 但不同类的另一个对象的最小距离。为此,我通过以下方式将数据分成块。
indexes <-
df %>%
select(partialId) %>%
unique()
j <- 1
library(doParallel)
class_separation <- c()
cl <- makePSOCKcluster(24)
registerDoParallel(cl)
while(j <= nrow(indexes)) {
test <- df %>% filter(partialId == indexes$partialId[j])
n <- nrow(test)
vec <- numeric(n)
vec <- foreach(k = 1:n, .combine = 'c', .multicombine = F) %dopar% {
c(
min(
apply(
test[test$uniqueId == test$uniqueId[k] & test$class != test$class[k], c("x","y")],
1,
function(x) dist(rbind(c(test$x[k],test$y[k]), c(x[1], x[2])))
)
)
)
}
class_separation <- c(class_separation, vec)
j <- j + 1
}
endtime <- Sys.time()
stopwatch <- endtime - starttime
closeAllConnections()
registerDoSEQ()
gc()
df <- cbind(df, class_separation)
在处理单次播放或小批量时,此代码似乎运行良好。但是,在处理完整数据集时,我得到的结果显然不正确。我知道我计算这些距离的方式一定有缺陷,因为 dist() 函数本身或 %dopar% 出错的可能性很小。我已更改为 %do% 并且我的结果没有改变。
作为差异的示例,下图显示了执行完整数据运行时的 class_separation 列与我提供一个小示例时的对比。如您所见,结果大相径庭,但我不确定为什么。
解决方案
经过一天的思考,问题在于我如何将我的 df 发送到 dist()。
例如,如果我们打算通过
dist(rbind(c(1, 1), c(6, 6)))
dist(rbind(c(1, 1), c(9, 9)))
我们实际通过的是dist(rbind(c(1, 1), c(6, 6, 9, 9)))
这显然不是我想要的。我需要两个距离,然后选择它们之间的最小值或添加其他条件。我发现的方法是使用 rdist 包。
foreach(i = 1:nrow(df), .combine = 'c', .multicombine = F, .packages = c('tidyverse',
'rdist')) %dopar% {
min(
cdist(
df[df$class != df$class[i] & df$uniqueId == df$uniqueId[i], ] %>% select(x, y),
df %>% select(x, y) %>% slice(i)
)
)
}
对于我们的测试数据,这将返回向量
Inf Inf Inf 2.828427 1.414214 1.414214 1.414214 1.414214 1.414214
这正是我所需要的。前三个条目的 uniqueId 没有 class == 1 选项应返回 Inf,第 4 行距第 6 行的距离是第 5 行的两倍,而它们都具有相同的 uniqueId,而第 9 行与第 8 行和第 10 行的距离相等。是否这个解决方案将足够快,我将进行测试。
推荐阅读
- laravel - 无法使用 axios 将带有数组参数的请求从 vue 发布到控制器
- javascript - 像 Shutterstock 一样的 CSS 网格布局
- android-studio - Android Studio 中的 Flutter 集成测试运行/调试配置
- c++ - 使命令不产生可执行文件
- react-native - 获取嵌套数据,未定义不是对象
- c# - 如何引用抽象类
- ruby-on-rails - 当 Parameter 包含非法值时,是否存在类似于 ActionController::UnpermittedParameters 的已定义异常?
- javascript - 用第二个数组中的名称替换数组中的 id
- asp.net-web-api - Web Api 控制器未解析操作
- python - 从范围生成python字典理解