向sf绘图添加自定义图例失败的问题排查
问题诊断与解决
这个错误的核心原因是plot.sf处理点图层时的参数逻辑,和你用layout()设置的布局、自定义图例函数.image_scale_factor()三者之间的绘图参数冲突了——具体来说是pin参数(控制绘图区域的宽高尺寸)被错误地修改,导致R无法识别有效的值。
为什么会出现这个情况?
plot.sf在绘制点图层时,会自动调整一系列绘图参数来适配点符号和分类配色;而layout()已经预先划分了绘图区域的布局,再加上.image_scale_factor()没有正确适配当前的布局上下文,三者叠加就触发了参数混乱。对比一下:
- 单独绘制多边形时,
plot.sf处理多边形的参数逻辑更简单,和layout的兼容性更好,所以不会报错; - 你单独绘制点的代码里还存在一个笔误:
brewer.pa(5, 'Paired')应该是brewer.pal(5, 'Paired'),不过这个笔误之外,核心还是参数冲突导致的pin错误。
解决方案
优先使用sf自带的图例功能,避免手动调用底层的图例函数,这样能让plot.sf自动处理参数适配,不会出现冲突。修改后的代码如下:
library(sf) library(magrittr) library(RColorBrewer) # 初始化数据 nc <- st_read(system.file("shape/nc.shp", package = "sf")) %>% st_transform(crs = 4326) points <- data.frame(p = seq(15, 75, 15), long = c(-85, -80, -78, -75, -82), lat = c(34, 36, 37, 38, 35)) %>% st_as_sf(coords = c('long', 'lat'), crs = 4326) points$p_cut <- cut(points$p, seq(0, 100, 20)) # 设置布局 layout(matrix(1:2, ncol = 2), widths = c(1, lcm(2))) # 绘制基础范围和多边形 bb_sol <- data.frame(long = c(-85, -75, -75, -85), lat = c(34, 34, 38, 38)) %>% st_as_sf(coords = c('long', 'lat'), crs = 4326) plot(st_geometry(bb_sol), axes = TRUE, graticule = TRUE, pch = '.') plot(st_geometry(nc), axes = TRUE, graticule = TRUE, add = TRUE) # 绘制点图层并让sf自动处理图例 plot(points['p_cut'], axes = TRUE, graticule = TRUE, pch = 16, pal = brewer.pal(5, 'Paired'), add = TRUE, key.pos = 4, key.length = lcm(8), key.width = lcm(2))
如果你一定要使用.image_scale_factor(),需要在调用plot.sf前先保存当前的绘图参数,绘制后恢复,同时修正笔误:
layout(matrix(1:2, ncol = 2), widths = c(1, lcm(2))) # 保存当前绘图参数 old_par <- par(no.readonly = TRUE) # 绘制点图层 plot(points['p_cut'], axes = TRUE, graticule = TRUE, pch = 16, key.pos = NULL, pal = brewer.pal(5, 'Paired')) # 恢复参数后调用图例函数 par(old_par) .image_scale_factor(levels(factor(points$p_cut)), col = brewer.pal(5, 'Paired'), key.length = lcm(8), key.width = lcm(2), key.pos = 4, at = 1:length(levels(points$p_cut)))
这样就能避免参数冲突导致的错误了。
内容的提问来源于stack exchange,提问作者noriega
相关产品推荐
相关产品推荐

