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

geom_tile图形配色优化:离散与连续变量结合设置需求

优化geom_tile空间数据可视化的实用方案

我明白你想要的核心效果:每个region用对比鲜明的主色调,同时在每个区域内部,根据region_relative_rainfall的连续值呈现同色系的深浅渐变。原代码里用全局连续渐变+region边框的方式,确实没法清晰区分不同区域的渐变趋势。下面给你几个从简单到进阶的优化思路,附完整代码:

方法1:分面展示(最直观,新手友好)

把每个region拆成单独的子图,每个子图内部用统一的渐变色系,同时用分面标题明确区分区域。这种方式能让每个区域的相对降雨量分布一目了然:

library(ggplot2)
library(dplyr)
library(viridis) # 提供好看的渐变配色,也可以用其他色系替代

# 你的原始数据生成代码
set.seed(123)
n_row = 10
n_col = 20
df = expand.grid(1:n_row, 1:n_col)
colnames(df) = c("y","x")
n = n_row * n_col
k = 5
df$region = sample(x = letters[1:k], size = n, replace = T)
df$rainfall = rlnorm(n = n, log(13), 0.4)
df <- df %>% group_by(region) %>% mutate("region_relative_rainfall" =rainfall / sum(rainfall))

# 分面可视化代码
ggplot(df, aes(x = x, y = y, fill = region_relative_rainfall)) + 
  geom_tile(color = "white", size = 0.1) + # 加细白边框,避免tile粘连
  facet_wrap(~region, ncol = 2) + # 按region分面,2列布局
  scale_fill_viridis(option = "plasma", name = "Relative Rainfall") + # 每个子图用同色系渐变
  theme_minimal() +
  theme(
    panel.grid = element_blank(), 
    axis.text = element_blank(),
    axis.title = element_blank(),
    strip.background = element_rect(fill = "grey90", color = NA), # 分面标题背景
    strip.text = element_text(face = "bold") # 加粗分面标题
  ) + 
  scale_y_reverse(lim=c(n_row,1))

方法2:同一画布内实现区域区分+子渐变(保留原始空间布局)

如果想保留所有tile在同一个画布的原始空间位置,不拆分分面,可以给每个region分配独特的主色相,然后在每个色相内根据相对降雨量调整亮度——数值越高,颜色越饱和明亮:

library(ggplot2)
library(dplyr)
library(colorspace) # 用于颜色亮度调整

# 数据生成部分同上,省略重复代码

# 给每个region分配高对比度的主色相
region_base_colors = c("a" = "#E64B35", "b" = "#4DBBD5", "c" = "#00A087", "d" = "#3C5488", "e" = "#F39B7F")

# 为每个tile计算对应的填充色:主色相的深浅变化
df <- df %>%
  group_by(region) %>%
  mutate(
    # 把当前region的relative rainfall归一化到0.3-1(避免太暗的颜色)
    norm_rain = scales::rescale(region_relative_rainfall, to = c(0.3, 1)),
    # 基于主色相生成渐变:数值越高,颜色越亮
    fill_color = lighten(region_base_colors[region], amount = 1 - norm_rain)
  ) %>%
  ungroup()

# 绘图
ggplot(df, aes(x = x, y = y, fill = fill_color, color = fill_color)) + 
  geom_tile(size = 0.1) +
  # 用identity映射自定义颜色,同时添加颜色条图例
  scale_fill_identity(name = "Relative Rainfall", 
                      guide = "colourbar",
                      labels = scales::percent_format()) +
  scale_color_identity() +
  theme_minimal() +
  theme(
    panel.grid = element_blank(), 
    axis.text = element_blank(),
    axis.title = element_blank()
  ) + 
  scale_y_reverse(lim=c(n_row,1))

方法3:多fill scale进阶方案(灵活控制每个区域的渐变)

如果需要更灵活的配置——比如每个region用完全不同的渐变类型(比如有的用冷色调,有的用暖色调),可以用ggnewscale包为每个region单独设置fill scale:

library(ggplot2)
library(dplyr)
library(ggnewscale) # 支持多fill/color scale

# 数据生成部分同上,省略重复代码

# 初始化画布
p <- ggplot() + 
  theme_minimal() +
  theme(
    panel.grid = element_blank(), 
    axis.text = element_blank(),
    axis.title = element_blank()
  ) + 
  scale_y_reverse(lim=c(n_row,1))

# 循环为每个region添加tile和对应的fill scale
for (r in unique(df$region)) {
  p <- p +
    geom_tile(
      data = df %>% filter(region == r),
      aes(x = x, y = y, fill = region_relative_rainfall),
      color = "white", size = 0.1
    ) +
    # 随机选不同的viridis渐变,也可以手动指定
    scale_fill_viridis(
      option = sample(c("viridis", "plasma", "magma", "inferno"), 1),
      name = paste("Region", r),
      limits = range(df$region_relative_rainfall[df$region == r])
    ) +
    new_scale_fill() # 切换到新的fill scale
}

# 调整图例布局并绘图
p <- p + guides(fill = guide_legend(ncol = 2))
print(p)

几个通用优化小技巧

  • 加细边框:用color="white", size=0.1给tile加细白边,能有效避免不同tile和区域之间的视觉粘连
  • 独立渐变范围:确保每个region的渐变是基于自身的region_relative_rainfall范围,而不是全局范围,这样能准确反映每个区域内部的差异
  • 高对比度配色:选主色相的时候尽量用色相差大的颜色,比如冷暖色搭配,避免相近色导致区分困难
  • 简化主题:去掉网格线、轴标签这些非必要元素,让视觉焦点完全集中在tile的颜色分布上

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:44:42