【问题标题】:How to input dissimilarity matrix in spatial analysis in spdep R如何在spdep R中的空间分析中输入相异矩阵
【发布时间】:2017-04-22 10:14:58
【问题描述】:

目标: 我想在坐标对之间创建一个相异矩阵。我想使用这个矩阵作为输入,使用 Moran's I (LISA) 和后者在地理加权回归 (GWR) 中计算局部空间集群。

问题: 我知道我可以使用dnearneigh{spdep} 来计算距离矩阵。但是,我想使用我已经估计的多边形之间的旅行时间。在实践中,我认为这就像输入一个相异矩阵,它根据另一个特征告诉多边形之间的距离/差异。我尝试将我的矩阵输入到dnearneigh{spdep},但我收到错误Error: ncol(x) == 2 is not TRUE

dist_matrix <- dnearneigh(diss_matrix_invers, d1=0, d2=5, longlat = F, row.names=rn)

有什么建议吗?下面有一个可重现的例子:

编辑:再深入一点,我想我可以使用mat2listw{spdep},但我仍然不确定它是否保持矩阵和多边形之间的对应关系。如果我添加 row.names = T 它会返回错误 row.names wrong length :(

listw_dissi <- mat2listw(diss_matrix_invers)
lmoran <- localmoran(oregon.tract@data$white, listw_dissi, 
                     zero.policy=T, alternative= "two.sided")

可重现的例子

library(UScensus2000tract)
library(spdep)
library(ggplot2)
library(dplyr)
library(reshape2)
library(magrittr)
library(data.table)
library(reshape)
library(rgeos)
library(geosphere)

# load data
  data("oregon.tract")

# get centroids as a data.frame
  centroids <- as.data.frame( gCentroid(oregon.tract, byid=TRUE) )

# Convert row names into first column
  setDT(centroids, keep.rownames = TRUE)[]

# create Origin-destination pairs
  od_pairs <- expand.grid.df(centroids, centroids) %>% setDT()
  colnames(od_pairs) <- c("origi_id", "long_orig", "lat_orig", "dest_id", "long_dest", "lat_dest")     

# calculate dissimilarity between each pair. 
# For the sake of this example, let's use ellipsoid distances. In my real case I have travel-time estimates
  od_pairs[ , dist := distGeo(matrix(c(long_orig, lat_orig), ncol = 2), 
                         matrix(c(long_dest, lat_dest), ncol = 2))]

# This is the format of how my travel-time estimates are organized, it has some missing values which include pairs of origin-destination that are too far (more than 2hours apart)
  od_pairs <- od_pairs[, .(origi_id, dest_id, dist)]
  od_pairs$dist[3] <- NA

  >      origi_id    dest_id         dist
  > 1:   oregon_0   oregon_0      0.00000
  > 2:   oregon_1   oregon_0           NA
  > 3:   oregon_2   oregon_0  39874.63673
  > 4:   oregon_3   oregon_0  31259.63100
  > 5:   oregon_4   oregon_0  33047.84249

# Convert to matrix
  diss_matrix <- acast(od_pairs, origi_id~dest_id, value.var="dist") %>% as.matrix()

# get an inverse matrix of distances, make sure diagonal=0
  diss_matrix_invers <- 1/diss_matrix
  diag(diss_matrix_invers) <- 0

计算简单距离矩阵

  # get row names
    rn <- sapply(slot(oregon.tract, "polygons"), function(x) slot(x, "ID"))
  # get centroids coordinates
    coords <- coordinates(oregon.tract)
  # get distance matrix
    diss_matrix <- dnearneigh(diss_matrix_invers, d1=0, d2=5, longlat =T, row.names=rn)

class(diss_matrix)
> [1] "nb"

现在如何在这里使用我的diss_matrix_invers

【问题讨论】:

  • 您的示例需要 rgeos 和 data.table 包(用于 gCentroid 和 setDT 等),以及 expand.grid.df 来自哪个包。您能否确保您的示例在干净的 R 会话中运行,以防丢失更多包?
  • 谢谢巴里。我刚刚添加了其他库。

标签: r cluster-analysis geospatial spdep gwr


【解决方案1】:

你对 matlistw{spdep} 的使用是正确的。默认情况下,该函数保留行的名称以保持矩阵之间的对应关系。您还可以像这样指定 row.names:

listw_dissi <- mat2listw(diss_matrix_invers, row.names = row.names(diss_matrix_invers))  

创建的列表将包含邻居的适当名称以及作为权重的距离。您可以通过查看邻居来检查这一点。

listw_dissi$neighbours[[1]][1:5]

而且你应该可以直接用它来计算 Moran's I。

dnearneigh{sdep}
您无法在 dnearneigh{spdep} 中使用 diss_matrix,因为此函数采用坐标列表。

但是,如果您需要使用自己的距离矩阵(行程时间)定义一组给定距离阈值 (d1,d2) 的邻居。我认为这个功能可以解决问题。

dis.neigh<-function(x, d1 = 0, d2=50){
  #x must be a symmetrical distance matrix
  #create empty list
  style = "M" #for style unknown
  neighbours<-list()
  weights<-list()
  #set attributes of neighbours list
  attr(neighbours, "class")<-"nb"
  attr(neighbours, "distances")<-c(d1,d2)
  attr(neighbours, "region.id")<-colnames(x)

  #check each row for neighbors that satisfy distance threshold
  neighbour<-c()
  weight<-c()
  i<-1
  for(row in c(1:nrow(x))){
    j<-1
    for(col in c(1:ncol(x))){
      if(x[row,col]>d1 && x[row,col]<d2){
        neighbour[j]<-col
        weight[j]<-1/x[row,col] #inverse distance (dissimilarity)
        j<-1+j
      }
    }
    neighbours[i]<-list(neighbour)
    weights[i]<-list(weight)
    i<-1+i
  }

  #create neighbour and weight list
  res <- list(style = style, neighbours = neighbours, weights = weights)
  class(res) <- c("listw", "nb")
  attr(res, "region.id") <- attr(neighbours, "region.id")
  attr(res, "call") <- match.call()

  return(res)
}

然后像这样使用它:

nb_list<-dis.neigh(diss_matrix, d1=0, d2=10000)
lmoran <- localmoran(oregon.tract@data$white, nb_lists, alternative= "two.sided")

【讨论】:

  • 谢谢马特奥。我也有一些来自太远(超过 2 小时)或不可能对(例如,起源于山上或湖中)的起点-目的地对的缺失值。我想我可以将这些对归为 0,因为它们在任何意义上都不是真正的邻居,对吗?
  • 是的,你可以为不是真正邻居的对估算 0,你只需要确保所有地方都至少有一个邻居,否则 localmoran() 会出错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-15
相关资源
最近更新 更多