【问题标题】:Efficiently running rdist.earth() with large data sets使用大型数据集高效运行 rdist.earth()
【发布时间】:2014-07-21 15:16:08
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: r


    【解决方案1】:

    有一种方法可以对函数进行向量化:

    来自同一个fields 包的rdist.earth.vec 计算输入位置的相应元素之间的成对大圆距离向量。

    我也遇到过类似的问题,虽然没有这么多的位置对。

    这是在 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+行的计算一眨眼就完成了。

    我希望这对某人有所帮助。

    【讨论】:

      【解决方案2】:

      对于无法使用生成的矩阵,您无能为力。这是一个巨大的密集矩阵。您可以通过存储一些结果而不是重新计算和使用 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。

      【讨论】:

        猜你喜欢
        • 2020-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-01
        相关资源
        最近更新 更多