在 ggplot 中绘制 nb 对象?

问题描述 投票:0回答:2

我想绘制英国的轮廓,以及我从空间点数据框生成的 nb 对象。

问题是英国的大纲需要非常非常长的时间来绘制——它一直让我的 Rstudio 崩溃。例如,要么加载时间很长,要么我的 Rstudio 停止响应。

library(raster)    
UK_gadm <- getData("GADM", country="GB", level=0)
    plot(UK_gadm)

所以我求助于从这个解决方案中使用ggplot2,在这里我可以使用以下命令在几分之一秒内获得英国的轮廓:

library(ggplot2)
UK <- map_data(map = "world", region = "UK") # changed map to "world"
    ggplot(data = UK, aes(x = long, y = lat, group = group)) + 
      geom_polygon() +
      coord_map()

现在的问题是,我希望 nb 对象在英国轮廓的背景下绘制——然而,这似乎只能在 base R 中实现,例如

plot(orotl.shp, xlim=c(-125, -115), ylim=c(42,47))
plot(orstationc.neighbors.dist, orstationc.loc, add=T, lwd=2, col="blue")

有没有什么办法可以在 ggplot 中绘制 nb 对象,或者有没有办法让 R 绘制英国的轮廓而不用基本的 R 绘图功能使我的计算机崩溃?

r ggplot2 geospatial spatial
2个回答
1
投票

经过一整夜的努力,设法找到了一个快速、简单的解决方案。希望这可以帮助其他有类似问题的人。

只是为了详细说明目标:针对 shapefile 绘制邻居对象 (nb)。这是为了可视化某些坐标之间的联系。经过一番谷歌搜索后,我认为这只能通过 base R 的 plot 函数来完成。然而,问题是加载一个国家的 shapefile(从官方来源/gadm 下载)——它太大了。

为了解决这个问题,通过 maps 包获取一个更通用、更简单的国家地图,将其转换为 shapefile,然后将其与 neighbors 对象一起绘制。

代码如下:

library(spdep)

# get your neighbour object from your spatial points df
rest_neighbours <- dnearneigh(rest_spdf,0,1)

library(maps)

# get boundary of UK
UK_map <- sf::st_as_sf(maps::map(database='world',regions='UK', plot = FALSE, fill = TRUE))

# write to shapefile
st_write(UK_map, 'shapefiles/UK.shp')

# henceforth, we can just call the shapefile 
UK <- readOGR('shapefiles/UK.shp')

# plot the boundary and the neighbours
plot(UK)
plot(rest_neighbours, rest_coords, add=T, lwd=2, col="blue")

我没有意识到官方边界文件通常非常详细,这也意味着它们非常庞大,我很高兴 r 的地图包中有现成的淡化地图版本。 (对不起,如果你已经知道了——我还在学习!)

希望这对其他人有帮助!


0
投票
  library(spdep)
  library(ggplot2)
  library(sf)
  
  # function converts nb object to a data.frame
  # with the coordinates of the lines "x"    "y"    "xend" "yend"
  nb_to_df <- function(nb, coords){
    x <- coords[, 1]
    y <- coords[, 2]
    n <- length(nb)
    cardnb <- card(nb)
    i <- rep(1:n, cardnb)
    j <- unlist(nb)
    return(data.frame(x=x[i], y=y[i], 
                      xend=x[j], yend=y[j]))
  }
  
  # Use this function to support the conversion of the dataframe to sf.  st_sf(st_sfc()) is needed in addition
  st_segment = function(r){sf::st_linestring(t(matrix(unlist(r), 2, 2)))} 
  #as we are not using here byrow=T, we have to use
  #transpose to have the format:
  #x1 y1
  #X2 Y2
  
  #Here one example
  ColData1 <- sf::st_read(system.file("shapes/columbus.shp", package="spData")[1], quiet=TRUE)
  coords1 = sf::st_coordinates(sf::st_centroid(ColData1)) # coordinates of the census tract centroids
  IDs1 = row.names(ColData1)
  ColData1$IDs1 = IDs1
  col_nb1 = poly2nb(ColData1, queen = TRUE)
  summary(col_nb1)
  class(col_nb1) # check the class of col_nb
  #A neighbours list with class nb (output of spdep::poly2nb )
  
  # this is a dataframe with the coordinates of the lines "x"    "y"    "xend" "yend"
  col_nb1_df = nb_to_df(col_nb1, coords1)
  
  col_nb1_df$geom = st_sfc(sapply(1:nrow(col_nb1_df), 
                                  function(i){st_segment(col_nb1_df[i,])}, simplify=FALSE)) 
  # the simplify = FALSE force to return LINESTRING (x1 y1, x2 y2)
  
  #convert to sf
  col_nb1_sf = sf::st_sf(col_nb1_df)
  
  # plot
  ggplot() +
    geom_sf(data=ColData1, fill=NA, color="red", lwd=0.5) +
    geom_sf(data=sf::st_centroid(ColData1), pch=19, color="blue") +
    geom_sf(data=col_nb1_sf, color="blue", lwd=0.3, lty=2) +
    geom_sf_label(data=ColData1, aes(label=IDs1), size = 2) +
    #geom_sf_text(data=ColData1, aes(label=IDs1), size = 3) +
    labs(title="Adjacency Connection", subtitle = "Columbus Shapefile") + 
    xlab("") +
    ylab("")
© www.soinside.com 2019 - 2024. All rights reserved.