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

tmap中成对地图点同步抖动防重叠的技术问题求助

解决tmap中同步抖动成对点并保持对应关系的问题

问题背景

使用tmap包绘制地图时,需要同时展示目标物种(pie$Species)和对应研究数量(pie$Number of effects)的点数据。直接叠加两组点会导致同位置的蓝色物种点与红色研究数量点重叠,无法区分;尝试重复设置相同随机种子并调用symbols.jitter参数时,同位置的成对点却分离,无法保持对应关联。

原始问题代码

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

# 数据
pie <- structure(list(Species = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), levels = c("Dingo (Canis familiaris)", 
"Feral cat (Felis catus)", "Red fox (Vulpes vulpes)"), class = "factor"), 
    latitude = c(-36.50086, -30.57784, -28.04301, -26.138, -21.47545, 
    -43.23844, -42.94019, -39.44835, -38.41747, -38.34843, -36.82553, 
    -34.91901, -33.88935, -33.68501, -31.5887, -31.37366, -30.38102, 
    -26.20224, -26.138, -25.84633, -25.81489, -25.75497, -23.52104, 
    -22.38505, -21.75822, -20.46208, -0.61152, -0.45597, -37.99066, 
    -36.76044, -36.00215, -35.04479, -32.13399, -31.98168, -30.38102, 
    -29.7344, -25.17532), longitude = c(148.26707, 152.37911, 
    117.89112, 121.352, 116.32237, 148.00311, 172.71215, 176.15995, 
    176.56565, 145.33848, 148.56044, 118.20129, 119.88379, 123.44054, 
    138.63257, 138.66283, 136.89996, 113.39237, 121.352, 113.89008, 
    113.05337, 113.54578, 149.21906, 118.79203, 116.01823, 115.52568, 
    -90.36483, -90.27174, 144.61613, 144.28746, 145.10796, 150.8078, 
    148.78329, 148.95018, 136.89996, 151.7338, 114.16974), `Number of effects` = c(1L, 
    10L, 4L, 1L, 3L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 5L, 3L, 
    1L, 5L, 7L, 2L, 1L, 5L, 44L, 2L, 3L, 2L, 1L, 1L, 1L, 2L, 
    4L, 1L, 1L, 1L, 1L, 1L, 2L, 1L)), row.names = c(NA, -37L), class = "data.frame")

# 格式化数据框
colnames(pie) <- c("Species", "latitude", "longitude", "Number of effects")
pie$latitude <- as.numeric(paste(pie$latitude))
pie$longitude <- as.numeric(paste(pie$longitude))

# 转换为空间数据框
pie.sf <- st_as_sf(pie, coords = c('longitude', 'latitude'), crs = 4326)

# 创建绘图边界框
bbox <- st_bbox(pie.sf) 

# 调整边界框
xrange <- bbox$xmax - bbox$xmin # x范围
yrange <- bbox$ymax - bbox$ymin # y范围
bbox[1] <- bbox[1] - (0.05 * xrange) # 左边界
bbox[3] <- bbox[3] + (0.2 * xrange) # 右边界
bbox[2] <- bbox[2] - (0.1 * yrange) # 下边界
bbox[4] <- bbox[4] + (0.1 * yrange) # 上边界

# 原始地图绘制
data("World")
tm_shape(World, bbox = bbox) + tm_borders() +
qtm(pie.sf, dots.col = 'Species', dots.palette = 'Blues', dots.size = 0.15) +
qtm(pie.sf, dots.col = 'Number of effects', dots.palette = 'Reds', dots.size = 0.03)

尝试的解决方案代码

# 尝试用相同随机种子调用symbols.jitter
p <- tm_shape(World, bbox = bbox) + tm_borders()

set.seed(123)
p <- p + qtm(pie.sf, dots.col = 'Species', dots.palette = 'Blues', dots.size = 0.15, symbols.jitter = 0.2)

set.seed(123)
p <- p + qtm(pie.sf, dots.col = 'Number of effects', dots.palette = 'Reds', dots.size = 0.03, symbols.jitter = 0.2)

正确解决方案

问题出在tmap的symbols.jitter内部实现,即使设置相同种子,两次调用的抖动逻辑可能不一致。正确做法是提前手动计算抖动偏移量,给两组点添加相同的偏移,确保成对点同步移位且保持对应:

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

# 复用前面的数据处理步骤(pie.sf和bbox已生成)
set.seed(123)
# 提取原始坐标矩阵
coords <- st_coordinates(pie.sf)
# 计算抖动偏移量:根据数据范围设置合适的抖动幅度
jitter_x <- jitter(coords[,1], amount = 0.5) - coords[,1]
jitter_y <- jitter(coords[,2], amount = 0.3) - coords[,2]

# 创建两组带同步偏移的空间数据框
# 物种点
pie_species <- pie.sf %>%
  mutate(geometry = geometry + st_sfc(st_multipoint(cbind(jitter_x, jitter_y)), crs = st_crs(pie.sf)))
# 研究数量点
pie_effects <- pie.sf %>%
  mutate(geometry = geometry + st_sfc(st_multipoint(cbind(jitter_x, jitter_y)), crs = st_crs(pie.sf)))

# 绘制地图
tm_shape(World, bbox = bbox) + tm_borders() +
  tm_shape(pie_species) + tm_dots(col = 'Species', palette = 'Blues', size = 0.15) +
  tm_shape(pie_effects) + tm_dots(col = 'Number of effects', palette = 'Reds', size = 0.03)

说明

  • 手动计算jitter_x和jitter_y作为偏移量,确保两组点使用完全相同的移位值
  • 通过geometry + st_sfc(...)给原始坐标添加偏移,生成新的空间对象
  • 使用tm_shape() + tm_dots()替代qtm(),更灵活控制图层,避免内部逻辑冲突
  • 可根据实际数据范围调整jitter()的amount参数,平衡抖动幅度和点的辨识度

内容的提问来源于stack exchange,提问作者Pat Taggart

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 09:59:54