如何通过sf包将ggplot2绘制的地图导出为GeoPDF?
解决ggplot2地图导出GeoPDF的问题
错误原因分析
你碰到的 Error in UseMethod("st_as_sf") : method not applicable for 'st_as_sf' applied to a class object "c('gg', 'ggplot')" 错误,核心原因很简单:sf::st_write() 是专门用来写入sf空间数据对象的工具,它完全无法识别ggplot生成的可视化对象(gg/ggplot类)。直接把ggplot图传给它,自然会出现类型不匹配的报错。
下面给你两种可行的解决方案,既能保留ggplot的定制化样式,又能生成带地理参考的PDF。
方案一:先导出普通PDF,再用GDAL添加地理参考
这是最灵活的方法——既可以用ggplot随心所欲定制地图样式,又能给成品PDF补上地理参考。需要用到gdalUtils包(前提是你的系统已经安装了GDAL工具,Windows可以通过OSGeo4W安装,macOS用Homebrew,Linux用包管理器比如apt-get install gdal-bin)。
完整代码示例
# 加载所需包 library(ggplot2) library(ggspatial) library(sf) library(gdalUtils) # 读取并处理数据 all.stands.predict <- read.csv("https://raw.githubusercontent.com/Leprechault/trash/main/prediction__bug_2021-03-18.csv") all.stands.predict <- all.stands.predict[all.stands.predict[,3]=="VILA PALMA",] sites <- st_as_sf(all.stands.predict, coords = c("x", "y"), crs = 4326, agr = "constant") # 绘制你需要的ggplot地图 gg <- ggplot() + geom_sf(data=sites, color="red") + annotation_north_arrow(location = "bl", which_north = "true", pad_x = unit(0.3, "in"), pad_y = unit(0.5, "in"), style = north_arrow_fancy_orienteering) + annotation_scale(location = "bl", width_hint = 0.55) + xlab("Longitude") + ylab("Latitude") + theme_bw() # 1. 先导出无地理参考的普通PDF ggsave("mymap_plain.pdf", plot = gg, device = "pdf") # 2. 获取数据的地理范围(用于给PDF添加参考) bbox <- st_bbox(sites) # 转换成GDAL需要的格式:xmin ymin xmax ymax bbox_str <- paste(bbox$xmin, bbox$ymin, bbox$xmax, bbox$ymax) # 3. 用gdal_translate给PDF添加地理参考,生成GeoPDF gdal_translate( src_dataset = "mymap_plain.pdf", dst_dataset = "mymap_georef.pdf", of = "PDF", a_srs = "EPSG:4326", # 匹配你的数据坐标系 a_ullr = bbox_str # 传入地理范围 )
方案二:用sf原生绘图生成GeoPDF(简化版)
如果你的地图不需要太复杂的ggplot定制(比如只需要基础的空间点展示),可以直接用sf::st_plot()绘图,再按同样的流程添加地理参考,步骤会更简洁:
代码示例
library(sf) library(gdalUtils) # 读取并处理数据(同方案一) all.stands.predict <- read.csv("https://raw.githubusercontent.com/Leprechault/trash/main/prediction__bug_2021-03-18.csv") all.stands.predict <- all.stands.predict[all.stands.predict[,3]=="VILA PALMA",] sites <- st_as_sf(all.stands.predict, coords = c("x", "y"), crs = 4326, agr = "constant") # 用st_plot绘制并导出普通PDF st_plot(sites, col = "red") ggsave("mymap_sf_plain.pdf") # 重复方案一的步骤添加地理参考 bbox <- st_bbox(sites) bbox_str <- paste(bbox$xmin, bbox$ymin, bbox$xmax, bbox$ymax) gdal_translate( src_dataset = "mymap_sf_plain.pdf", dst_dataset = "mymap_sf_georef.pdf", of = "PDF", a_srs = "EPSG:4326", a_ullr = bbox_str )
注意事项
- 如果你的ggplot地图手动设置了
xlim/ylim缩放范围,一定要把bbox换成你实际显示的范围,而不是原始数据的边界,否则地理参考会错位。 - 确认GDAL工具安装成功:可以在终端输入
gdalinfo --version检查,R里的gdalUtils包需要依赖系统级的GDAL。
内容的提问来源于stack exchange,提问作者Leprechault
相关产品推荐
相关产品推荐

