使用 ggplot2 绘制具有多个子多边形和孔的 SpatialPolygons
Draw SpatialPolygons with multiple subpolygons and holes using ggplot2
我想从库 sp
中绘制 SpatialPolygons
,但 ggplot2 中存在漏洞。
感谢关于 Whosebug 的其他问题,我知道在处理顺时针书写的多边形时这是允许的:
实际上,当使用 broom::tidy
(替换 ggplot2::fortify
)转换 SpatialPolygons
时,孔多边形按顺时针方向保存以绘制为孔。
在 ggplot2 中,绘制带孔的多边形的方式强制使用 fill
绘制一次,另一次使用 colour
,否则您可能会看到穿过多边形的线。
当处理多个子多边形时,有些有孔,这更棘手,broom::tidy
定义的点特征的顺序可能不允许填充多边形(见下图)。
你们有解决这个填充问题行为的方法吗?
这是一个可重现的例子:
library(sp)
library(ggplot2)
# Create two polygons: second would be a hole inside the first
xy = cbind(
x = c(13.4, 13.4, 13.6, 13.6, 13.4),
y = c(48.9, 49, 49, 48.9, 48.9)
)
hole.xy <- cbind(
x = c(13.5, 13.5, 13.45, 13.45, 13.5),
y = c(48.98, 48.92, 48.92, 48.98, 48.98)
)
# Transform as SpatialPolygons with holes
xy.sp <- SpatialPolygons(list(
Polygons(list(Polygon(xy),
Polygon(hole.xy, hole = TRUE)), "1"),
Polygons(list(Polygon(xy + 0.2),
Polygon(xy + 0.35),
Polygon(hole.xy + 0.2, hole = TRUE)), "2")
))
# Transform SpatialObject to be used by ggplot2
xy.sp.l <- broom::tidy(xy.sp)
ggplot(xy.sp.l) +
geom_polygon(aes(x = long, y = lat, group = id, fill = id))
(来源:statnmap.com)
可能是 "go over" 到 sf
包的好时机。由于 geom_sf
几何结构:
,在 ggplot
中使用 sf
对象实际上要容易得多
library("sf")
library("rgeos")
sf_poly <- as(xy.sp, "sf")
sf::st_crs(sf_poly) <- 4326
sf_poly$id <- c(1,2)
ggplot(sf_poly) +
geom_sf(aes(fill = as.factor(id)))
添加行显示问题的根源。正在绘制蓝色 "polygon",下部 -> 上部 -> 孔。
此代码(不是很优雅,抱歉)使路径在继续到第 3 段之前返回到第 1 段的起点。
library(dplyr)
extra <- xy.sp.l %>%
filter(piece != 1) %>%
group_by(id, group) %>%
summarise(last_pt = max(order))
for (n in 1:nrow(extra)) {
id_ex <- as.character(extra[n,"id"])
x <- subset(xy.sp.l, id == id_ex & piece == 1 & order == 1)
x$order <- as.numeric(extra[n,"last_pt"]) + 0.5
xy.sp.l <- rbind(xy.sp.l,x)
}
xy.sp.l <- xy.sp.l[order(xy.sp.l$id, xy.sp.l$order),]
这个 post 是个好问题,已经收到了很好的答案。我也相信人们应该学习如何使用 sf
对象,因为它是 R 中的下一代空间数据类型。但我想在这种情况下分享 geom_spatial
来自 ggspatial
包可能是绘制 SpatialPolygons 的一个选项。
library(sp)
library(ggplot2)
library(ggspatial)
ggplot() +
geom_spatial(xy.sp, aes(fill = id))
# Ignoring argument 'mapping' in geom_spatial.SpatialPolygons
# Autodetect projection: assuming lat/lon (epsg 4326)
我想从库 sp
中绘制 SpatialPolygons
,但 ggplot2 中存在漏洞。
感谢关于 Whosebug 的其他问题,我知道在处理顺时针书写的多边形时这是允许的:
实际上,当使用 broom::tidy
(替换 ggplot2::fortify
)转换 SpatialPolygons
时,孔多边形按顺时针方向保存以绘制为孔。
在 ggplot2 中,绘制带孔的多边形的方式强制使用 fill
绘制一次,另一次使用 colour
,否则您可能会看到穿过多边形的线。
当处理多个子多边形时,有些有孔,这更棘手,broom::tidy
定义的点特征的顺序可能不允许填充多边形(见下图)。
你们有解决这个填充问题行为的方法吗?
这是一个可重现的例子:
library(sp)
library(ggplot2)
# Create two polygons: second would be a hole inside the first
xy = cbind(
x = c(13.4, 13.4, 13.6, 13.6, 13.4),
y = c(48.9, 49, 49, 48.9, 48.9)
)
hole.xy <- cbind(
x = c(13.5, 13.5, 13.45, 13.45, 13.5),
y = c(48.98, 48.92, 48.92, 48.98, 48.98)
)
# Transform as SpatialPolygons with holes
xy.sp <- SpatialPolygons(list(
Polygons(list(Polygon(xy),
Polygon(hole.xy, hole = TRUE)), "1"),
Polygons(list(Polygon(xy + 0.2),
Polygon(xy + 0.35),
Polygon(hole.xy + 0.2, hole = TRUE)), "2")
))
# Transform SpatialObject to be used by ggplot2
xy.sp.l <- broom::tidy(xy.sp)
ggplot(xy.sp.l) +
geom_polygon(aes(x = long, y = lat, group = id, fill = id))
(来源:statnmap.com)
可能是 "go over" 到 sf
包的好时机。由于 geom_sf
几何结构:
ggplot
中使用 sf
对象实际上要容易得多
library("sf")
library("rgeos")
sf_poly <- as(xy.sp, "sf")
sf::st_crs(sf_poly) <- 4326
sf_poly$id <- c(1,2)
ggplot(sf_poly) +
geom_sf(aes(fill = as.factor(id)))
添加行显示问题的根源。正在绘制蓝色 "polygon",下部 -> 上部 -> 孔。
此代码(不是很优雅,抱歉)使路径在继续到第 3 段之前返回到第 1 段的起点。
library(dplyr)
extra <- xy.sp.l %>%
filter(piece != 1) %>%
group_by(id, group) %>%
summarise(last_pt = max(order))
for (n in 1:nrow(extra)) {
id_ex <- as.character(extra[n,"id"])
x <- subset(xy.sp.l, id == id_ex & piece == 1 & order == 1)
x$order <- as.numeric(extra[n,"last_pt"]) + 0.5
xy.sp.l <- rbind(xy.sp.l,x)
}
xy.sp.l <- xy.sp.l[order(xy.sp.l$id, xy.sp.l$order),]
这个 post 是个好问题,已经收到了很好的答案。我也相信人们应该学习如何使用 sf
对象,因为它是 R 中的下一代空间数据类型。但我想在这种情况下分享 geom_spatial
来自 ggspatial
包可能是绘制 SpatialPolygons 的一个选项。
library(sp)
library(ggplot2)
library(ggspatial)
ggplot() +
geom_spatial(xy.sp, aes(fill = id))
# Ignoring argument 'mapping' in geom_spatial.SpatialPolygons
# Autodetect projection: assuming lat/lon (epsg 4326)