使用大型数据集高效运行rdist.earth()

时间:2014-07-21 15:16:09

标签: r

我是R的新手,目前正在使用字段包中的rdist.earth()函数来计算坐标对之间的距离。我的问题是我的数据集非常大,几乎不可能运行该函数。我目前正在运行以下代码。

   distance.matrix <- round(5280 * rdist.earth(x, y, miles = TRUE))

x数据帧有~1040000行,y有~1200。 我必须在服务器上运行它以使其工作,并且它仍然需要很长时间来计算。返回的距离矩阵大约为8 gb,几乎无法使用。

有没有办法对rdist.earth()或其他策略进行矢量化,以便我可以更有效地运行它?

2 个答案:

答案 0 :(得分:2)

有一种矢量化功能的方法:

来自同一rdist.earth.vec包的

fields计算一个输入位置的相应元素之间成对的大圆距离的向量。

我也遇到了类似的问题,尽管没有那么多的位置对。

在2400 * 2400位置矩阵中,这对我有用。 我在一个数据帧(?combn())中将所有位置组合成双对,然后称为rdist.earth.vec

dyadic$GCD <- rdist.earth.vec(x1 =dyadic[,c("lon_orig","lat_orig")],
                              x2 =dyadic[,c("lon_dest","lat_dest")],
                              miles = FALSE)

眨眼就完成了对2.M +行的计算。

我希望这对某人有帮助。

答案 1 :(得分:0)

关于无法使用生成的矩阵,您无能为力。这是一个巨大的密集矩阵。您可以通过存储一些结果而不是重新计算和使用tcrossprod来加速rdist.earth函数:

library(fields)

rdist.earth2 <- function(x1, x2, miles = TRUE, R = NULL){
  if (is.null(R)) {
    if (miles) 
      R <- 3963.34
    else R <- 6378.388
  }
  x1 <- x1 / 180
  x2 <- x2 / 180
  x1cs <- cbind(cospi(x1), sinpi(x1))
  x2cs <- cbind(cospi(x2), sinpi(x2))
  pp <- tcrossprod(cbind(x1cs[,1] * x1cs[,2], x1cs[,2] * x1cs[,3], x1cs[,4]),
                   cbind(x2cs[,1] * x2cs[,2], x2cs[,2] * x2cs[,3], x2cs[,4]))
  pp <- pmin(pmax(-1, pp), 1)
  matrix(R * acos(pp), nrow = nrow(x1), ncol = nrow(x2))
}



rlat     <- function(n) runif(n, -90, 90)
rlong    <- function(n) runif(n, -180, 180)
rlatlong <- function(n) cbind(rlong(n), rlat(n))
x1 <- rlatlong(1000)
x2 <- rlatlong(1000)

system.time(ans1 <- rdist.earth(x1, x2))
system.time(ans2 <- rdist.earth2(x1, x2))
identical(all.equal(ans1, ans2), TRUE)

我的速度提高了30%,而且内存效率似乎更高。您也可以将其拆分并尝试并行执行。

library(iterator)
library(foreach)
ans3 <- foreach(b = iter(x1, by = 'row', chunksize = 100000L ), .combine='rbind') %do% rdist.earth2(b, x2)
identical(all.equal(ans1, ans3), TRUE)

您必须注册并行后端并将%do%替换为%dopar%。这对速度没有多大帮助,但它可能让你在你的机器而不是服务器上进行,具体取决于你有多少内存。我可以在我的机器上用16 Gb RAM做1000000 * 1000。