R语言绘制sf地图时locator函数定位点位置错位问题
问题原因
- 核心诱因是
sf包的base绘图方法默认设置reset = TRUE:绘图完成后会自动将R的绘图参数(含坐标范围usr、纵横比asp等)恢复到绘图前的初始状态。这就导致肉眼看到的图面坐标(带自动扩展边距、固定纵横比)和R后台生效的坐标映射规则完全不一致,后续locator()捕获的点击坐标、points()绘制点位使用的都是重置后的错误坐标规则,最终出现点位错位。 - 观察到的x轴显示范围小于数据边界框xmin的现象,是
plot.sf默认asp = 1(强制x、y轴1个坐标单位的屏幕物理长度相等,避免要素变形)的自动适配行为:研究区经纬度跨度对应的固有宽高比,和当前R绘图设备(如RStudio Plots面板)的宽高比不匹配,R会自动在x轴两侧补充空白边距来满足纵横比要求,这部分范围属于图面显示留白,不属于数据本身的边界范围。
解决方法
方案1:最小改动修复
绘图时显式设置reset = FALSE,让绘图完成后后台坐标系统和图面显示保持一致即可,不需要修改其他逻辑:
plot(spainCoast_CoteBanyuls$geometry, axes = T, reset = FALSE) A1 <- locator(1) print(A1) points(A1, col = "red", pch = 16) # 绘制的点位将和点击位置完全对齐
注意:绘图代码运行前不要手动调整绘图面板大小,否则可能触发重绘导致坐标错位。
方案2:去掉多余留白+保证要素不变形
手动指定绘图范围为数据真实边界框,同时设置对应纬度的正确纵横比,既不会出现多余白边,也不会拉伸海岸矢量的形状:
# 提取数据真实边界框 data_bbox <- st_bbox(spainCoast_CoteBanyuls) # 计算研究区中心纬度对应的正确纵横比 center_lat <- mean(c(data_bbox$ymin, data_bbox$ymax)) correct_asp <- 1/cos(center_lat * pi/180) plot( spainCoast_CoteBanyuls$geometry, axes = T, reset = FALSE, xlim = c(data_bbox$xmin, data_bbox$xmax), ylim = c(data_bbox$ymin, data_bbox$ymax), asp = correct_asp ) A1 <- locator(1) points(A1, col = "red", pch = 16)
方案3:使用ggplot2体系做交互选点
如果后续有更多可视化、选点需求,换用ggplot2绘图,配合gginnards包的gglocator()函数选点,从机制上避免base绘图的参数重置问题:
library(ggplot2) library(gginnards) # 绘制地图 p <- ggplot() + geom_sf(data = spainCoast_CoteBanyuls, linewidth = 0.5) + coord_sf() # 自动处理坐标范围、纵横比 print(p) # 交互选点 A1 <- gglocator(n = 1, geom = "point", col = "red", pch = 16) print(A1)
内容的提问来源于stack exchange,提问作者CharlotteS.
相关产品推荐
相关产品推荐

