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

如何为ggplot分面地图设置不同的scale_fill_gradient高端颜色?

问题

使用ggplot()和geom_sf()绘制分面地图,通过value变量用scale_fill_gradient2()为地图单元着色,按group变量分面。当前单渐变填充正常,但希望按分面设置渐变高端的颜色(Group A高值为红色,Group B高值为绿色)。已在数据框中添加color_high列,但无法将该列颜色值应用到填充渐变中,求实现方法。

附可运行的单渐变填充代码:

library(sf)
library(tidyverse)
theme_set(theme_bw())
library(giscoR)

ger_fedstates <- gisco_get_nuts(nuts_level = 1, resolution = 10, country = "Germany", year = 2021)

dat <- read.table(text = "state value group
                          Sachsen 10 a
                          Sachsen 1 b
                          Bayern 3 a
                          Bayern 30 b
                          Rheinland-Pfalz 50 a
                          Rheinland-Pfalz 50 b
                          Saarland 70 a
                          Saarland 70 b
                          Schleswig-Holstein 9 a
                          Schleswig-Holstein 90 b
                          Niedersachsen  100 a
                          Niedersachsen  100 b
                          Nordrhein-Westfalen 80 a
                          Nordrhein-Westfalen 80 b
                          Baden-Württemberg 60 a
                          Baden-Württemberg 60 b
                          Brandenburg 40 a
                          Brandenburg 40 b
                          Mecklenburg-Vorpommern 20 a
                          Mecklenburg-Vorpommern 20 b
                          Bremen 40 a
                          Bremen 40 b
                          Hamburg 60 a
                          Hamburg 60 b
                          Hessen 15 a
                          Hessen 15 b
                          Berlin 10 a
                          Berlin 10 b
                          Thüringen 80 a
                          Thüringen 80 b
                          Sachsen-Anhalt 20 a
                          Sachsen-Anhalt 20 b", header = T) %>% 
  mutate(color_high = case_when(group=="a"~"red", group=="b"~"green"))

plot_df <- full_join(ger_fedstates, dat, by=c("NUTS_NAME" = "state"))

plot_df %>% 
  ggplot() +
  geom_sf(aes(fill = value)) +
  theme(axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        axis.line.x = element_blank(),
        axis.line.y = element_blank(),
        legend.position = "right",
        legend.title.align = 0) +
  scale_fill_gradient2(low = "grey40",
                       mid = "white",
                       high = "#0000ff", # 这里希望用color_high列的值
                       midpoint=50,
                       guide = "colourbar",
                       aesthetics = "fill") + 
  facet_wrap(~group, labeller = labeller(group=c(a="Group A", b="Group B", c="Group C")))

预期效果:Group A高值显示红色,Group B高值显示绿色。


解决方案

单一的scale_fill_gradient2无法直接实现分面动态渐变颜色,因为它是全局生效的。以下提供两种可行实现方式:

方法1:自定义调色逻辑(无需额外包)

核心思路是按group归一化value,结合color_high列的颜色构建渐变映射,适合需要统一颜色条的场景:

library(sf)
library(tidyverse)
theme_set(theme_bw())
library(giscoR)

ger_fedstates <- gisco_get_nuts(nuts_level = 1, resolution = 10, country = "Germany", year = 2021)

dat <- read.table(text = "state value group
                          Sachsen 10 a
                          Sachsen 1 b
                          Bayern 3 a
                          Bayern 30 b
                          Rheinland-Pfalz 50 a
                          Rheinland-Pfalz 50 b
                          Saarland 70 a
                          Saarland 70 b
                          Schleswig-Holstein 9 a
                          Schleswig-Holstein 90 b
                          Niedersachsen  100 a
                          Niedersachsen  100 b
                          Nordrhein-Westfalen 80 a
                          Nordrhein-Westfalen 80 b
                          Baden-Württemberg 60 a
                          Baden-Württemberg 60 b
                          Brandenburg 40 a
                          Brandenburg 40 b
                          Mecklenburg-Vorpommern 20 a
                          Mecklenburg-Vorpommern 20 b
                          Bremen 40 a
                          Bremen 40 b
                          Hamburg 60 a
                          Hamburg 60 b
                          Hessen 15 a
                          Hessen 15 b
                          Berlin 10 a
                          Berlin 10 b
                          Thüringen 80 a
                          Thüringen 80 b
                          Sachsen-Anhalt 20 a
                          Sachsen-Anhalt 20 b", header = T) %>% 
  mutate(color_high = case_when(group=="a"~"red", group=="b"~"green")) %>%
  # 按group归一化value,将每个组的value映射到0-1区间
  group_by(group) %>%
  mutate(norm_value = scales::rescale(value, to = c(0,1))) %>%
  ungroup()

plot_df <- full_join(ger_fedstates, dat, by=c("NUTS_NAME" = "state"))

plot_df %>% 
  ggplot() +
  geom_sf(aes(fill = norm_value, color = color_high)) +
  # 基础渐变:从深灰到白色
  scale_fill_gradient2(low = "grey40", mid = "white", high = "white", midpoint = 0.5, guide = "none") +
  # 用color_high的颜色作为渐变终点,通过alpha映射归一化后的value
  scale_color_identity(aesthetics = c("fill"), 
                       guide = "colourbar",
                       breaks = c(0, 0.5, 1),
                       labels = c(min(plot_df$value), 50, max(plot_df$value))) +
  theme(axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        axis.line.x = element_blank(),
        axis.line.y = element_blank(),
        legend.position = "right",
        legend.title.align = 0) +
  labs(fill = "Value") +
  facet_wrap(~group, labeller = labeller(group=c(a="Group A", b="Group B", c="Group C")))

方法2:使用ggnewscale实现分面独立刻度

如果需要每个分面保留独立的颜色条,可以用ggnewscale为每个group设置单独的填充刻度:

library(sf)
library(tidyverse)
theme_set(theme_bw())
library(giscoR)
library(ggnewscale)

ger_fedstates <- gisco_get_nuts(nuts_level = 1, resolution = 10, country = "Germany", year = 2021)

dat <- read.table(text = "state value group
                          Sachsen 10 a
                          Sachsen 1 b
                          Bayern 3 a
                          Bayern 30 b
                          Rheinland-Pfalz 50 a
                          Rheinland-Pfalz 50 b
                          Saarland 70 a
                          Saarland 70 b
                          Schleswig-Holstein 9 a
                          Schleswig-Holstein 90 b
                          Niedersachsen  100 a
                          Niedersachsen  100 b
                          Nordrhein-Westfalen 80 a
                          Nordrhein-Westfalen 80 b
                          Baden-Württemberg 60 a
                          Baden-Württemberg 60 b
                          Brandenburg 40 a
                          Brandenburg 40 b
                          Mecklenburg-Vorpommern 20 a
                          Mecklenburg-Vorpommern 20 b
                          Bremen 40 a
                          Bremen 40 b
                          Hamburg 60 a
                          Hamburg 60 b
                          Hessen 15 a
                          Hessen 15 b
                          Berlin 10 a
                          Berlin 10 b
                          Thüringen 80 a
                          Thüringen 80 b
                          Sachsen-Anhalt 20 a
                          Sachsen-Anhalt 20 b", header = T) %>% 
  mutate(color_high = case_when(group=="a"~"red", group=="b"~"green"))

plot_df <- full_join(ger_fedstates, dat, by=c("NUTS_NAME" = "state"))

ggplot() +
  # 绘制Group A的地图及对应渐变刻度
  geom_sf(data = filter(plot_df, group == "a"), aes(fill = value)) +
  scale_fill_gradient2(low = "grey40", mid = "white", high = "red", midpoint = 50, name = "Group A Value") +
  # 开启新的填充刻度上下文
  new_scale_fill() +
  # 绘制Group B的地图及对应渐变刻度
  geom_sf(data = filter(plot_df, group == "b"), aes(fill = value)) +
  scale_fill_gradient2(low = "grey40", mid = "white", high = "green", midpoint = 50, name = "Group B Value") +
  theme(axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        axis.line.x = element_blank(),
        axis.line.y = element_blank(),
        legend.position = "right",
        legend.title.align = 0) +
  facet_wrap(~group, labeller = labeller(group=c(a="Group A", b="Group B", c="Group C")))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 15:35:27