问题描述
问题:我们需要一种大数据方法来计算点之间的距离。我们在下面用五个观测数据框概述我们想要做的事情。但是,由于行数变大(>;100万),这种特定的方法是不可行的。在过去,我们使用SAS来进行这种分析,但如果可能的话,我们更倾向于使用R。(注意:我不打算显示代码,因为虽然我在下面概述了一种在较小的数据集上执行此操作的方法,但这基本上不可能用于我们规模的数据。)
我们从商店的数据帧开始,每个商店都有纬度和经度(尽管这不是空间文件,我们也不想使用空间文件)。
# you can think of x and y in this example as Cartesian coordinates
stores <- data.frame(id = 1:5,
x = c(1, 0, 1, 2, 0),
y = c(1, 2, 0, 2, 0))
stores
id x y
1 1 1 1
2 2 0 2
3 3 1 0
4 4 2 2
5 5 0 0
对于每个商店,我们想知道x距离内的商店数量。在小型数据帧中,这很简单。创建所有坐标的另一个数据帧,合并回来,计算距离,如果距离小于x,则创建一个指示器,并将指示器相加(商店本身的指示器减去1,距离为0)。这将产生如下所示的数据集:
id x y s1.dist s2.dist s3.dist s4.dist s5.dist
1: 1 1 1 0.000000 1.414214 1.000000 1.414214 1.414214
2: 2 0 2 1.414214 0.000000 2.236068 2.000000 2.000000
3: 3 1 0 1.000000 2.236068 0.000000 2.236068 1.000000
4: 4 2 2 1.414214 2.000000 2.236068 0.000000 2.828427
5: 5 0 0 1.414214 2.000000 1.000000 2.828427 0.000000
当您(任意)将1.45以下计算为关闭时,您最终得到的指标如下:
# don't include the store itself in the total
id x y s1.close s2.close s3.close s4.close s5.close total.close
1: 1 1 1 1 1 1 1 1 4
2: 2 0 2 1 1 0 0 0 1
3: 3 1 0 1 0 1 0 1 2
4: 4 2 2 1 0 0 1 0 1
5: 5 0 0 1 0 1 0 1 2
最终产品应如下所示:
id total.close
1: 1 4
2: 2 1
3: 3 2
4: 4 1
5: 5 2
感谢所有建议。
非常感谢
推荐答案
有什么原因不能循环,而不是进行大计算?
stores <- data.frame(id = 1:5,
x = c(1, 0, 1, 2, 0),
y = c(1, 2, 0, 2, 0))
# Here's a Euclidean distance metric, but you can drop anything you want in here
distfun <- function(x0, y0, x1, y1){
sqrt((x1-x0)^2+(y1-y0)^2)
}
# Loop over each store
t(sapply(seq_len(nrow(stores)), function(i){
distances <- distfun(x0 = stores$x[i], x1 = stores$x,
y0 = stores$y[i], y1 = stores$y)
# Calculate number less than arbitrary cutoff, subtract one for self
num_within <- sum(distances<1.45)-1
c(stores$id[i], num_within)
}))
生产:
[,1] [,2]
[1,] 1 4
[2,] 2 1
[3,] 3 2
[4,] 4 1
[5,] 5 2
这将适用于您可以引入R的任何大小的数据集,但随着大小的增加,它只会变得更慢。下面是在我的机器上几秒钟内运行的对10,000个条目的测试:
stores <- data.frame(id=1:10000,
x=runif(10000, max = 10),
y=runif(10000, max = 10))
[,1] [,2]
[1,] 1 679
[2,] 2 698
[3,] 3 618
[4,] 4 434
[5,] 5 402
...
[9995,] 9995 529
[9996,] 9996 626
[9997,] 9997 649
[9998,] 9998 514
[9999,] 9999 667
[10000,] 10000 603
计算越多,它就越慢(因为它必须在每对点之间运行,这将始终是O(n^2)),但在不知道要计算的实际距离度量的情况下,我们无法进一步优化较慢的部分。