从同一矩阵中的所有其他行值中减去行值

时间:2015-10-07 15:37:55

标签: r matrix gis apply pythagorean

我有一个包含地理位置(两列)和在场/禁欲数据(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循环转换为我可以在整个数据框中逐行应用函数中使用的函数。但我确实怀疑,应用函数是可行的,对吗?

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

1 个答案:

答案 0 :(得分:1)

您可以尝试将其移动到apply语句中,并将数据子集化为具有值的数据。

首先,制作一个新的df,只有那些在yesno中有1s的df(没有点计算那些不需要求和的距离):

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]

})