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

如何为ggplot分面地图的每个分面设置对应政党渐变配色?

问题:为每个政党分面地图设置对应渐变配色

需求说明

我用ggplot绘制欧洲社会调查(ESS)的政党偏好数据,要给每个政党做单独的分面地图,每个分面用对应政党的颜色,颜色越深代表得票越多。

数据结构

head(party_votes_summary)

# A tibble: 5 × 7
# Groups:   NUTS_NAME [5]
  NUTS_NAME   all_votes    total_votes                  geometry percentage_votes                geometry.y
  <chr>       <fct>              <int>        <MULTIPOLYGON [m]>            <dbl>        <MULTIPOLYGON [m]>
1 Centro (IT) Forza Italia          18 (((4358646 2346312, 4371…          0.0111  (((4358646 2346312, 4371…
2 Isole       Fratelli d'…           0 (((4787072 1652570, 4774…         NA                           EMPTY
3 Nord-Est    Altro                 34 (((4510729 2621661, 4527…          0.0209  (((4510729 2621661, 4527…
4 Nord-Ovest  Forza Italia          37 (((4386364 2524813, 4371…          0.0228  (((4386364 2524813, 4371…
5 Sud         Fratelli d'…          16 (((4945372 2007501, 4997…          0.00984 (((4945372 2007501, 4997…
# ℹ 1 more variable: NUTS_ID <chr>

当前代码

ggplot(party_votes_summary) +
  geom_sf(aes(fill = total_votes, geometry = geometry), color = "black") +
  facet_wrap(~ all_votes, labeller = labeller(all_votes = c(
    "Partido Democratico (PD)" = "Partido Democratico",
    "Sinistra Ecologia e Libertà (SEL)" = "Sinistra Ecologia e Libertà",
    "Popolo delle Libertà (PdL)" = "Popolo delle Libertà"
    ))) +
  labs(title = "Summary of Votes per Party per Region",
       fill = "Party") +
  theme(axis.text.x = element_blank(),  
        axis.text.y = element_blank(),  
        axis.ticks = element_blank())+
  scale_fill_distiller(palette = "Blues", direction = 1) 

尝试修改后的代码及报错

修改后的代码:

ggplot(party_votes_summary) +
  geom_sf(aes(fill = total_votes, geometry = geometry), color = "black") +
  facet_wrap(~ all_votes, labeller = labeller(all_votes = c(
    "Partido Democratico (PD)" = "Partido Democratico",
    "Sinistra Ecologia e Libertà (SEL)" = "Sinistra Ecologia e Libertà",
    "Popolo delle Libertà (PdL)" = "Popolo delle Libertà"
    ))) +
  labs(title = "Summary of Votes per Party per Region",
       fill = "Party") +
  theme(axis.text.x = element_blank(),  
        axis.text.y = element_blank(),  
        axis.ticks = element_blank())+
  scale_fill_manual(values = party_palette)

报错信息:

Error in scale_fill_manual():
! Continuous values supplied to discrete scale.
ℹ Example values: 261, 261, 261, 261, and 261

尝试过的颜色向量

party_colours <- c("Movimento 5 Stelle" = "#EED924",
"Lega" = "#008000",
"Partido Democratico (PD)" = "#DC143C",
"Forza Italia" = "#0087DC",
"Fratelli d'Italia" = "darkblue",
"SVP-PATT"="#8a8a8a",
"+ Europa" = "darkgreen",
"Altro"="whitesmoke",
"Sinistra Ecologia e Libertà (SEL)"="palegreen2",
"Liberi e Uguali" = "darkred",
"Popolo delle Libertà (PdL)" = "#0099DC",
"La Destra" = "royalblue")

party_palette <- c(
"Movimento 5 Stelle" = scale_fill_brewer(palette = "OrRd"),
"Lega" = scale_fill_brewer(palette = "Greens"),
"Partido Democratico (PD)" = scale_fill_brewer(palette = "Reds"),
"Forza Italia" = scale_fill_brewer(palette = "Blues"),
"Fratelli d'Italia" = scale_fill_brewer(palette = "Blues"),
"SVP-PATT" = scale_fill_brewer(palette = "Greys"),
"+ Europa" = scale_fill_brewer(palette = "Greens"),
"Altro" = scale_fill_brewer(palette = "Greys"),
"Sinistra Ecologia e Libertà (SEL)" = scale_fill_brewer(palette = "Greens"),
"Liberi e Uguali" = scale_fill_brewer(palette = "Reds"),
"Popolo delle Libertà (PdL)" = scale_fill_brewer(palette = "Blues"),
"La Destra" = scale_fill_brewer(palette = "Blues"))

解决方案

核心问题是total_votes是连续变量,不能用离散的scale_fill_manual,且ggplot默认不支持为每个分面单独设置渐变配色。以下提供两种可行方法:

方法1:用ggh4x实现分面专属渐变配色

  1. 安装并加载依赖包:
install.packages("ggh4x")
library(ggh4x)
library(dplyr)
library(purrr)
library(scales)
  1. 预处理数据,为每个政党的得票做归一化并映射到对应渐变色:
# 定义每个政党的渐变色区间(浅-主色-深)
party_pal_map <- list(
  "Movimento 5 Stelle" = gradient_n_pal(c("#FFFFE0", "#EED924", "#D4A017"))(seq(0,1,length.out=100)),
  "Lega" = gradient_n_pal(c("#E8F5E9", "#008000", "#005000"))(seq(0,1,length.out=100)),
  "Partido Democratico (PD)" = gradient_n_pal(c("#FFEBEE", "#DC143C", "#990011"))(seq(0,1,length.out=100)),
  "Forza Italia" = gradient_n_pal(c("#E3F2FD", "#0087DC", "#005A9E"))(seq(0,1,length.out=100)),
  "Fratelli d'Italia" = gradient_n_pal(c("#E3F2FD", "darkblue", "#003366"))(seq(0,1,length.out=100)),
  "SVP-PATT" = gradient_n_pal(c("#F5F5F5", "#8a8a8a", "#555555"))(seq(0,1,length.out=100)),
  "+ Europa" = gradient_n_pal(c("#E8F5E9", "darkgreen", "#004D00"))(seq(0,1,length.out=100)),
  "Altro" = gradient_n_pal(c("#FFFFFF", "whitesmoke", "#CCCCCC"))(seq(0,1,length.out=100)),
  "Sinistra Ecologia e Libertà (SEL)" = gradient_n_pal(c("#E8F5E9", "palegreen2", "#66BB6A"))(seq(0,1,length.out=100)),
  "Liberi e Uguali" = gradient_n_pal(c("#FFEBEE", "darkred", "#880000"))(seq(0,1,length.out=100)),
  "Popolo delle Libertà (PdL)" = gradient_n_pal(c("#E3F2FD", "#0099DC", "#006699"))(seq(0,1,length.out=100)),
  "La Destra" = gradient_n_pal(c("#E3F2FD", "royalblue", "#0047AB"))(seq(0,1,length.out=100))
)

# 归一化得票并匹配颜色
party_votes_summary <- party_votes_summary %>%
  group_by(all_votes) %>%
  mutate(norm_votes = rescale(total_votes, to = c(0,1))) %>%
  ungroup() %>%
  mutate(fill_col = map2_chr(all_votes, norm_votes, ~ party_pal_map[[.x]][round(.y*99)+1]))
  1. 绘制分面地图:
ggplot(party_votes_summary) +
  geom_sf(aes(fill = fill_col, geometry = geometry), color = "black") +
  facet_wrap2(~ all_votes, labeller = labeller(all_votes = c(
    "Partido Democratico (PD)" = "Partido Democratico",
    "Sinistra Ecologia e Libertà (SEL)" = "Sinistra Ecologia e Libertà",
    "Popolo delle Libertà (PdL)" = "Popolo delle Libertà"
  ))) +
  labs(title = "Summary of Votes per Party per Region") +
  theme(axis.text.x = element_blank(),  
        axis.text.y = element_blank(),  
        axis.ticks = element_blank(),
        legend.position = "none") +
  scale_fill_identity()

方法2:拆分数据逐个绘图再拼接

  1. 安装并加载依赖包:
install.packages(c("purrr", "patchwork"))
library(purrr)
library(patchwork)
library(scales)
  1. 定义单个政党的绘图函数:
plot_party <- function(party_data, party_name) {
  # 获取政党主色并生成渐变调色板
  main_col <- party_colours[[party_name]]
  pal <- gradient_n_pal(c(lighten(main_col, 0.5), main_col, darken(main_col, 0.5)))(seq(0,1,length.out=100))
  
  ggplot(party_data) +
    geom_sf(aes(fill = total_votes, geometry = geometry), color = "black") +
    scale_fill_gradientn(colours = pal, na.value = "white") +
    labs(title = party_name, fill = "得票数") +
    theme(axis.text.x = element_blank(),  
          axis.text.y = element_blank(),  
          axis.ticks = element_blank(),
          plot.title = element_text(size=10))
}
  1. 拆分数据并拼接所有图表:
# 按政党拆分数据
party_list <- split(party_votes_summary, party_votes_summary$all_votes)

# 生成每个政党的地图
plots <- imap(party_list, plot_party)

# 拼接成统一布局
wrap_plots(plots, ncol=3) +
  plot_annotation(title = "Summary of Votes per Party per Region")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 07:52:06