1

我有一个包含地理位置(两列)和存在/禁欲数据(0/1)的数据框。我需要找出的是,有多少其他位置位于其附近并且值为 1。然后应将该数字附加到第四列中。

xcoords <- c(4487754, 4488111, 4487598, 4487417, 4487949, 4487802, 4488011, 4487638, 4487455, 4487478, 4487141, 4487550, 4487547, 4488010, 4487271, 4487170)
ycoords <- c(5294654, 5294706, 5295490, 5293859, 5295313, 5294910, 5294668, 5295399, 5294537, 5294408, 5294927, 5294617, 5294727, 5294953, 5294168, 5295142)
yesno <- round(runif(16, 0, 1),0) 
df <- cbind(xcoords, ycoords, yesno)

我将附近设置为 500 米(地理数据位于投影坐标系中,因此单位对应),并将使用毕达哥拉斯定理进行计算。

buffer <- 500

我所知道的是如何构建嵌套的 for 循环。但我不希望我的函数看起来像这样:

count.in.buffer <- function(df, buffer){
lon <- df$xcoords
lat <- df$ycoords
count <- rep(0, length(lon))
 for(i in 1:length(lon)){        # for every row...
  for(j in 1:length(lon) - 1){   # ... check all other rows
    nolon <- lon[-i]
    nolat <- lat[-i]
    ifelse(sqrt((abs(lon[i] - nolon[j]))^2 + (abs(lat[i] - nolat[j]))^2) < buffer, ifelse(df$yesno == 1, count[i] <- count[i] + 1, count[i] <- count[i] + 0), count[i] <- count[i] + 0)
   }
  }
 result <- cbind(data, count)
 return(result)
}

这需要很长时间才能计算出来,因为我的数据框实际上有 67000 行。

相反,我想要更高效的东西,但我不明白如何将内部 for 循环转换为我可以在整个数据帧的应用函数中逐行使用的函数。但我确实怀疑,应用功能将是要走的路,对吧?

PS:我已经用适当的 GIS 解决了这个问题,通过在每个数据点周围创建缓冲区多边形并将其他数据点链接到每个缓冲区多边形的属性表(如果它们位于该缓冲区内)。但我认为在 R 中应该更快。

4

1 回答 1

1

您可以尝试将其移动到应用语句中,并将您的数据子集到具有值的那些中。

首先,创建一个新的 df ,其中只有在 yesno 中具有 1 的那些(对于那些没有求和的对象计算距离没有意义):

df1 <- df[df[ ,'yesno'] == 1,]

然后,我们以向量化的方式将 df 的每一行与所有 df1 进行比较,并对计数求和(减去我们的初始计数,因此我们不计算两次):

apply(df, 1, function(x){
    sum(sqrt((x[1] - df1[ ,1])^2 +
             (x[2] - df1[ ,2])^2) < buffer) - x[3]

})
于 2015-10-07T15:52:44.773 回答