You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R语言中使用tmap为地图多边形添加对应数量的多点?

R语言tmap绘制带内部点的区域地图解决方案

问题描述

作为R语言地图绘制新手,使用tmap处理里约健康区域shp文件,现有数据框如下:

data <- data.frame(COD_AP_SMS = c("AP 1.0", "AP 2.1", "AP 2.2", "AP 3.1", "AP 3.2", "AP 3.3", "AP 4.0", "AP 5.1", "AP 5.2", "AP 5.3"),
                   n = c(11, 21, 6, 32, 15, 32, 27, 26, 19, 18))

需求:

  1. 每个COD_AP_SMS对应的多边形用不同颜色区分
  2. 每个多边形内生成对应n数量的点(如AP 1.0区域内生成11个点)

现有代码使用tm_dots("n")仅控制点的大小,无法生成对应数量的点,当前效果为区域颜色区分但点不符合需求,期望效果是每个区域内均匀分布对应数量的点。

现有代码:

ap <- read_sf("shp/Limites AP.shp")

plot(ap)

ap <- full_join(ap, tb, by = "COD_AP_SMS")

# 调整边界框
bbox_new <- st_bbox(ap) # 当前边界框
xrange <- bbox_new$xmax - bbox_new$xmin # x轴范围
yrange <- bbox_new$ymax - bbox_new$ymin # y轴范围

bbox_new[3] <- bbox_new[3] + (0.25 * xrange) # 扩展右侧边界
bbox_new[4] <- bbox_new[4] + (0.2 * yrange) # 扩展顶部边界

bbox_new <- bbox_new %>%  # 转换为sf多边形
  st_as_sfc()

tm_shape(ap, bbox = bbox_new)+
  tm_fill("COD_AP_SMS", auto.palette.mapping=FALSE, 
          title="AP")+ 
  tm_dots("n", size = 2) +
  tm_compass(position = c("left", "top"))+
  tm_scale_bar(position = c("left", "top"))+
  tm_borders(alpha=1, lwd = 1, col = "black")+ 
  tm_legend(legend.format = list(text.separator= "a")) +
  tm_layout(legend.position = c("right", "top"),
            frame = FALSE)

解决方案

核心是先为每个多边形生成对应数量的随机点,再用tmap分层绘制多边形和点:

1. 生成区域内的点集

使用sf包的st_sample函数,对每个区域生成指定数量的随机点:

library(sf)
library(tmap)
library(dplyr)

# 读取并合并数据
ap <- read_sf("shp/Limites AP.shp")
data <- data.frame(COD_AP_SMS = c("AP 1.0", "AP 2.1", "AP 2.2", "AP 3.1", "AP 3.2", "AP 3.3", "AP 4.0", "AP 5.1", "AP 5.2", "AP 5.3"),
                   n = c(11, 21, 6, 32, 15, 32, 27, 26, 19, 18))
ap <- ap %>% inner_join(data, by = "COD_AP_SMS")

# 生成每个区域内的随机点
points_list <- lapply(1:nrow(ap), function(i) {
  st_sample(ap[i, ], size = ap$n[i]) %>%
    st_sf() %>%
    mutate(COD_AP_SMS = ap$COD_AP_SMS[i])
})
all_points <- do.call(rbind, points_list)

2. 绘制符合需求的地图

分层绘制多边形、边界和点,同时优化地图元素:

# 保留原有边界框设置
bbox_new <- st_bbox(ap)
xrange <- bbox_new$xmax - bbox_new$xmin
yrange <- bbox_new$ymax - bbox_new$ymin
bbox_new[3] <- bbox_new[3] + (0.25 * xrange)
bbox_new[4] <- bbox_new[4] + (0.2 * yrange)
bbox_new <- st_as_sfc(bbox_new)

# 绘制地图
tm_shape(ap, bbox = bbox_new) +
  tm_fill("COD_AP_SMS", auto.palette.mapping = FALSE, 
          title = "健康区域(AP)", palette = "Set3") + # 用Set3调色板增强区分度
  tm_borders(alpha = 1, lwd = 1, col = "black") +
  tm_shape(all_points) +
  tm_dots(size = 0.5, col = "white", alpha = 0.8) + # 白色点与彩色区域形成对比
  tm_compass(position = c("left", "top"), type = "4star", size = 2, color = "black") +
  tm_scale_bar(position = c("left", "top"), width = 0.2, text.size = 0.8, 
               color.dark = "black", color.light = "white") +
  tm_text("COD_AP_SMS", size = 0.7, col = "black", just = "center") + # 添加区域标签
  tm_layout(
    legend.position = c("right", "top"),
    frame = FALSE,
    legend.title.size = 1,
    legend.text.size = 0.8,
    main.title = "里约健康区域及对应点数分布",
    main.title.size = 1.2,
    main.title.position = "center"
  )

优化建议

  • 标签优化:如果区域标签重叠,可调整size参数或使用tm_text的auto.placement = TRUE自动避让。
  • 颜色优化:若默认调色板区分度不足,可使用palette = RColorBrewer::brewer.pal(10, "Paired")自定义调色板。
  • 比例尺与指南针:将指南针和比例尺位置错开(如指南针在左上,比例尺在左下),避免重叠;调整size和text.size适配地图整体尺寸。
  • 点样式:可根据需求修改点的颜色(如与区域颜色一致)或形状(shape = 16为实心圆)。

内容的提问来源于stack exchange,提问作者Lana Meijinhos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 03:18:11