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

在ggplot geom_sf地图中为geom_tile添加水平渐变填充

解决地图中添加水平渐变填充矩形的问题

问题描述

制作地图时,希望添加左侧颜色最深、向右渐变为白色的水平渐变填充矩形。最初用geom_rect绘制矩形,参考示例尝试带fill变量的geom_tile,生成存储xmax与xmin差值的虚拟列newcol,但矩形仍无渐变效果。

原代码如下:

library(ggplot2)
library(sf)
library(rnaturalearth)
library(tidyverse)

states <- ne_states(country = c("United States of America","Canada"), returnclass = "sf")

rectangles <- data_frame(
  y = (35:44)+0.5, 
  xmin = c(-75.5, -75.770333, -75.683333, -75.916667, -74.613, -74.0315, 
           -71.916667, -70.666667, -70.466667, -68.4), 
  xmax = c(-74.8, -74.616667, -73.983333, -72.8, -69.216667, -66.416667, 
           -65.65, -65.675833, -66.516667, -66.721667)
)%>% 
  pivot_longer(cols = c(xmax, xmin), names_to="identity", values_to="x") %>% 
  group_by(y) %>% 
  mutate(meanx = mean(x),
         newcol = x - min(x)) 

ggplot(data = states) +
  geom_sf() +
  geom_tile(data = rectangles, aes(x=meanx, y=y, width=2, height=1, fill=newcol), color="black") +
  scale_fill_gradient(low="darkblue", high="white") +
  coord_sf(xlim = c(-80, -65), ylim = c(34, 45.5), expand = FALSE) +
  NULL

原效果:
原效果无渐变的矩形

解决方案

原方法失效的原因是:每个geom_tile对应一个完整的矩形区域,即使设置了fill变量,每个tile也只会显示单一颜色,无法实现区域内的渐变。

正确思路是将每个大矩形拆分为大量细小的垂直条带,每个条带对应x轴上的一个小区间,通过给每个条带分配对应位置的颜色值,模拟出从左到右的渐变效果。

修改后的代码

library(ggplot2)
library(sf)
library(rnaturalearth)
library(tidyverse)

# 获取地图数据
states <- ne_states(country = c("United States of America","Canada"), returnclass = "sf")

# 定义矩形参数,保留每个矩形的y、xmin、xmax原始信息
rect_params <- tibble(
  y = (35:44)+0.5, 
  xmin = c(-75.5, -75.770333, -75.683333, -75.916667, -74.613, -74.0315, 
           -71.916667, -70.666667, -70.466667, -68.4), 
  xmax = c(-74.8, -74.616667, -73.983333, -72.8, -69.216667, -66.416667, 
           -65.65, -65.675833, -66.516667, -66.721667)
)

# 为每个矩形生成密集x点,拆分出细小垂直条带
rectangles <- rect_params %>%
  group_by(y, xmin, xmax) %>%
  summarize(x = seq(xmin, xmax, length.out = 100),  # 生成100个点,数量越多渐变越平滑
            .groups = "drop") %>%
  mutate(
    fill_val = (x - xmin)/(xmax - xmin)  # 计算相对位置,0对应左端点(最深色),1对应右端点(白色)
  )

# 绘图
ggplot(data = states) +
  geom_sf() +
  # 用细小tile模拟渐变,width设为条带宽度,隐藏条带边框避免缝隙
  geom_tile(data = rectangles, aes(x = x, y = y, width = (xmax - xmin)/99, height = 1, fill = fill_val), color = NA) +
  # 添加大矩形的黑色边框,保证外观完整
  geom_rect(data = rect_params, aes(xmin = xmin, xmax = xmax, ymin = y - 0.5, ymax = y + 0.5), fill = NA, color = "black") +
  scale_fill_gradient(low = "darkblue", high = "white") +
  coord_sf(xlim = c(-80, -65), ylim = c(34, 45.5), expand = FALSE) +
  theme_minimal()

代码解释

  1. 保留矩形原始范围:不再对xmin和xmax做pivot_longer,直接保留每个矩形的完整边界参数。
  2. 生成密集x采样点:对每个矩形用seq生成100个均匀分布的x点,点的数量越多,渐变过渡越自然平滑。
  3. 计算相对填充比例:fill_val是当前x点距离左端点的相对比例,取值范围0到1,完美匹配渐变的深浅变化。
  4. 分层绘制元素:先用无框小tile绘制渐变填充,再用geom_rect叠加黑色边框,既实现渐变效果,又保证矩形的完整轮廓。

内容的提问来源于stack exchange,提问作者Alexa Fredston

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:35:30