我想绘制英国的轮廓,以及我从空间点数据框生成的 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 绘图功能使我的计算机崩溃?
经过一整夜的努力,设法找到了一个快速、简单的解决方案。希望这可以帮助其他有类似问题的人。
只是为了详细说明目标:针对 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 的地图包中有现成的淡化地图版本。 (对不起,如果你已经知道了——我还在学习!)
希望这对其他人有帮助!
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("")