R语言中基于sf绘制带比例符号的地区叠加地图问题求助
问题描述
我通过sf包导入了一个包含某拉美国家1874个地区的GeoDataFrame,数据结构如下:
Classes ‘sf’ and 'data.frame': 1874 obs. of 8 variables: $ NOMBDIST: chr "CODO DEL POZUZO" "TOURNAVISTA" "ALEXANDER VON HUMBOLDT" "IRAZOLA" ... $ POBTOTAL: num 7768 6219 6085 10941 9003 ... $ UBIGEO : num 100902 100904 250305 250302 250304 ... $ MC_PR : num 41 41.4 46 43.8 35.3 ... $ C_PR : num 9.23 5.22 3.27 2.64 2.21 ... $ TT : num 1084 556 1530 2769 1535 ... $ IDH : num 0.324 0.409 0.423 0.378 0.437 ... $ geom :sfc_MULTIPOLYGON of length 1874; first list element: List of 1 ..$ :List of 1 .. ..$ : num [1:1294, 1:2] -75.3 -75.3 -75.3 -75.3 -75.3 ... ..- attr(*, "class")= chr [1:3] "XY" "MULTIPOLYGON" "sfg" - attr(*, "sf_column")= chr "geom" - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA ..- attr(*, "names")= chr [1:7] "NOMBDIST" "POBTOTAL" "UBIGEO" "MC_PR" ...
字段说明:
NOMBDIST:地区名称POBTOTAL:地区总人口UBIGEO:地区编码MC_PR:科研岗位女性占比C_PR:科研岗位从业者占比TT:总劳动者数IDH:人类发展指数
我想要制作一张地图:以灰色地区为背景,在每个地区的中心点绘制点,点的大小由TT字段决定,颜色随MC_PR字段渐变。尝试了以下代码,但结果不符合预期:
ggplot() + geom_sf(data = gdf, fill = "grey95") + geom_sf(data = centroides, pch = 21, aes(size = TT, fill = MC_PR), col = "grey20") + xlim(c(2200000, 7150000)) + ylim(c(1380000, 5500000)) + scale_size(range = c(1, 9), guide = guide_legend( direction = "horizontal", nrow = 1, label.position = "bottom")) + scale_fill_gradientn(colours = hcl.colors(5, "RdBu", rev = TRUE,alpha = 0.9)) + guides(fill = guide_legend(title = "")) + theme_void() + theme(legend.position = "bottom")
解决方案
从代码和预期效果来看,问题集中在中心点数据处理和图例配置上,以下是修正步骤:
1. 正确生成地区中心点
确保centroides是从原始GeoDataFrame正确计算得到的中心点,且保留所需字段:
# 计算每个地区的中心点(优先取最大面的中心,适配多边形地区) centroides <- st_centroid(gdf, of_largest_polygon = TRUE) # 保留绘图需要的字段 centroides <- centroides %>% select(NOMBDIST, TT, MC_PR, geom)
若原始数据是经纬度坐标系(如EPSG:4326),直接使用st_centroid即可;若是投影坐标系也能正常计算。
2. 修正颜色渐变的图例配置
MC_PR是连续数值,不能用离散的guide_legend,需改用guide_colourbar显示渐变条:
scale_fill_gradientn( colours = hcl.colors(5, "RdBu", rev = TRUE, alpha = 0.9), name = "科研岗位女性占比(%)" # 自定义颜色图例标题 ) + guides( size = guide_legend( direction = "horizontal", nrow = 1, label.position = "bottom", title = "总劳动者数" # 自定义大小图例标题 ), fill = guide_colourbar( direction = "horizontal", barwidth = 15, barheight = 1, title.position = "top" ) )
3. 优化地图范围裁剪方式
用xlim/ylim容易裁剪掉地理要素,建议先通过st_crop裁剪原始数据:
# 定义裁剪范围(需匹配原始数据的坐标系) bbox <- st_bbox(c(xmin = 2200000, ymin = 1380000, xmax = 7150000, ymax = 5500000), crs = st_crs(gdf)) gdf_cropped <- st_crop(gdf, bbox) centroides_cropped <- st_crop(centroides, bbox) # 最终绘图代码 ggplot() + geom_sf(data = gdf_cropped, fill = "grey95", color = "white", size = 0.1) + # 添加细边框区分地区 geom_sf(data = centroides_cropped, pch = 21, aes(size = TT, fill = MC_PR), color = "grey20") + scale_size(range = c(1, 9), guide = guide_legend( direction = "horizontal", nrow = 1, label.position = "bottom", title = "总劳动者数" )) + scale_fill_gradientn( colours = hcl.colors(5, "RdBu", rev = TRUE, alpha = 0.9), name = "科研岗位女性占比(%)" ) + guides( fill = guide_colourbar( direction = "horizontal", barwidth = 15, barheight = 1, title.position = "top" ) ) + theme_void() + theme( legend.position = "bottom", legend.box = "vertical", legend.margin = margin(10, 10, 10, 10) )
4. 额外优化建议
- 给背景地区添加细白色边框,能更清晰区分不同区域;
- 若点重叠严重,可添加
alpha = 0.8参数降低点的透明度; - 调整
scale_size的range参数,可控制点的大小区间。
内容的提问来源于stack exchange,提问作者José Carlos Rojas
相关产品推荐
相关产品推荐

