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

R语言空间分析:根据点到质心距离设置点位绘制大小

需求说明

我是R语言与空间分析初学者,需要实现空间可视化效果:绘制德累斯顿(属性编码SN_L = 14、RS = 14612)县域质心30km缓冲区范围内的所有监测站点点位,点位大小和站点到县域质心的距离负相关——距质心越近点位尺寸越大,用距离倒数映射点位大小。

已完成的基础代码

目前已经实现基础版地图:点位尺寸统一,按是否落在缓冲区分色,代码如下:

### 计算县域质心
counties_trans$centroid <- st_centroid(counties_trans$geometry)

#------------------------------------------------------------------------------#

### 生成质心30km缓冲区
counties_trans$buff <- st_buffer(counties_trans$centroid, 30000)

#------------------------------------------------------------------------------#

### 提取研究范围:德累斯顿所在的萨克森州区域
# 定义州边界范围框
box = c(xmin = 703301, ymin = 5562792, xmax = 921778, ymax = 5733351)
saxony <- st_crop(counties_trans, box)

# 提取德累斯顿质心30km缓冲区范围内的站点
a <- st_intersection(saxony$buff[which(saxony$RS == "14612")], poll_st_trans$geometry)

# 提取30km缓冲区外的所有站点
c <- st_difference(poll_st_trans$geometry, saxony$buff[which(saxony$RS == "14612")])

# 提取萨克森州范围内、30km缓冲区外的站点
d <- st_intersection(c, saxony$geometry[which(saxony$SN_L == "14")])

#------------------------------------------------------------------------------#

### 绘制基础地图
# 绘制萨克森州县域边界
plot(saxony$geometry[which(saxony$SN_L == "14")], reset = FALSE)

# 绘制德累斯顿质心
plot(saxony$centroid[which(saxony$RS == "14612")], add = TRUE, pch = 20)

# 绘制30km缓冲区边界
plot(saxony$buff[which(saxony$RS == "14612")], add = TRUE)

# 绘制州内缓冲区外的站点
plot(d, add = TRUE, pch = 24, col = 'grey')

# 绘制缓冲区内的站点(此处点位大小设置失效)
plot(a, add = TRUE, pch = 17, col = 'royalblue3', cex = dist)

# 绘制萨克森州外的其他区域
plot(saxony$geometry[which(saxony$SN_L != "14")], add = TRUE, col = 'grey')

已经通过如下代码计算缓冲区内各站点到德累斯顿质心的距离:

dist <- st_distance(a, saxony$centroid[which(saxony$RS == "14612")])

遇到的问题

尝试在base R的plot函数中传入cex = dist、在ggplot2的geom_sf图层传入size = dist设置点位大小,两种方式都只显示整块蓝色矩形,无法得到按距离映射大小的点位效果,异常效果如下:
点位大小设置失效的异常出图效果


解决方法

错误原因

出图异常核心是两个问题:

  1. st_distance()返回值是带units单位属性的二维矩阵,不是普通一维数值向量,直接传给绘图参数无法被正确解析
  2. 需求是距离越近点位越大,直接用原始距离映射的话,距离越远数值越大、点位尺寸越大,和需求逻辑完全相反

具体修正步骤

第一步:处理距离值

计算完距离后,先把距离转为普通数值,再做倒数缩放,把值映射到适合点位大小的区间:

# 去除单位属性和矩阵结构,转为普通数值向量
dist <- as.numeric(dist)
# 计算距离倒数,缩放到合适的cex取值区间,避免点过大或过小
# 方法1:手动缩放
point_cex <- (1/dist) * max(dist) * 0.8
# 方法2:用scales包归一化,固定cex范围在0.6~2.5,效果更可控
# point_cex <- scales::rescale(1/dist, to = c(0.6, 2.5))

第二步:修正base R绘图代码

base R的plot.sf()方法对sf对象绘图时,不支持直接传入和要素等长的cex向量,需要提取站点坐标后用points()函数单独绘制点位:

# 提取缓冲区内站点的平面坐标
a_coords <- st_coordinates(a)

# 替换原代码中plot(a, ...)的部分
points(
  x = a_coords[,1], 
  y = a_coords[,2],
  pch = 17, 
  col = 'royalblue3', 
  cex = point_cex
)

可选:ggplot2版本正确写法

如果用ggplot2绘制,需要把点位大小作为属性列加入sf对象,在aes()内部做属性映射,不要把外部向量直接传给size参数:

library(ggplot2)
# 将计算好的点位大小写入站点sf对象
a$point_size <- point_cex

ggplot() +
  # 绘制萨克森州县域边界
  geom_sf(data = saxony[saxony$SN_L == "14",], fill = NA, linewidth = 0.3) +
  # 绘制萨克森州外的邻接区域
  geom_sf(data = saxony[saxony$SN_L != "14",], fill = "grey90", color = NA) +
  # 绘制30km缓冲区边界
  geom_sf(data = saxony$buff[saxony$RS == "14612"], fill = NA, linetype = "dashed", linewidth = 0.5) +
  # 绘制缓冲区外的州内站点
  geom_sf(data = d, pch = 24, col = "grey50", fill = "grey80", size = 1.5) +
  # 绘制缓冲区内的站点,映射size属性
  geom_sf(data = a, pch = 17, col = "royalblue3", aes(size = point_size)) +
  # 绘制德累斯顿质心
  geom_sf(data = saxony$centroid[saxony$RS == "14612"], pch = 20, size = 2) +
  # 隐藏size图例
  scale_size_continuous(guide = "none") +
  theme_minimal()

内容的提问来源于stack exchange,提问作者Stefano Ceolotto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:15:39