我的数据大致采用以下格式,但非常大,但使用类和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列与我提供给它的一个小示例。正如你所看到的,结果是非常不同的,但我不确定为什么。

发布于 2020-02-28 08:02:41
经过一天的思考,问题出在我如何将我的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)
)
)
}对于我们的测试数据,这将返回向量
信息2.828427 1.414214 1.414214 1.414214
这正是我想要的。uniqueId没有类== 1选项的前三个条目应该返回Inf,行4到行6的距离是行5的两倍,而所有行都具有相同的uniqueId,而行9到行8和行10的距离相等。我将测试此解决方案是否足够快。
https://stackoverflow.com/questions/60426700
复制相似问题