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

求助:为热图各列设置独立scale_fill_discrete的实现问题

实现每列独立填充比例尺的热图解决方案

我明白你想要的是共享y轴(车型名称)、每列对应独立填充色比例尺的热图,你用ggnewscale的思路完全找对方向了!最后那段代码的问题主要是x轴位置没对齐,导致各列的瓷砖重叠或者位置混乱,咱们来调整一下就能达到目标:

第一步:预处理数据,给每列分配固定的x位置

首先咱们给每个key(也就是vs、am这些变量)分配一个固定的x坐标,这样每个变量对应的列在x轴上的位置是确定的,不会乱掉:

library(tidyverse)
library(ggnewscale)
library(ggsci)

# 数据预处理:转成因子、整理格式,添加x位置列
temp <- mtcars %>%
  rownames_to_column("rnames") %>%
  as_tibble() %>%
  mutate(across(-rnames, as_factor)) %>%  # 把数值列转成因子,保证填充色是离散型
  select(rnames, vs, am, gear, carb) %>%
  gather(key = "key", value = "value", -rnames) %>%
  mutate(
    key = fct_inorder(key),  # 保留变量原来的顺序
    x_pos = as.numeric(key)  # 给每个key分配对应的x轴位置
  )

第二步:构建带独立填充比例尺的热图

接下来咱们用ggnewscale的new_scale_fill()来分隔每个图层的填充比例尺,每个变量对应一个geom_tile图层,并且搭配你想要的ggsci配色:

ggplot(temp, aes(y = rnames)) +
  # 第一列:vs,用Simpsons配色
  geom_tile(data = filter(temp, key == "vs"),
            aes(x = x_pos, fill = value)) +
  scale_fill_simpsons(name = "vs") +
  new_scale_fill() +  # 开启新的填充比例尺上下文
  
  # 第二列:am,用Rick&Morty配色
  geom_tile(data = filter(temp, key == "am"),
            aes(x = x_pos, fill = value)) +
  scale_fill_rickandmorty(name = "am") +
  new_scale_fill() +
  
  # 第三列:gear,用Futurama配色
  geom_tile(data = filter(temp, key == "gear"),
            aes(x = x_pos, fill = value)) +
  scale_fill_futurama(name = "gear") +
  new_scale_fill() +
  
  # 第四列:carb,用Tron配色
  geom_tile(data = filter(temp, key == "carb"),
            aes(x = x_pos, fill = value)) +
  scale_fill_tron(name = "carb") +
  
  # 调整x轴刻度,显示变量名称
  scale_x_continuous(breaks = unique(temp$x_pos),
                     labels = unique(temp$key)) +
  labs(x = "变量", y = "车型") +
  theme_minimal() +
  # 整理图例:放在底部,垂直排列
  theme(legend.position = "bottom",
        legend.box = "vertical")

(可选)用循环简化代码

如果变量多的话,重复写图层太麻烦,咱们可以用循环来自动添加每个图层和对应的比例尺:

# 先定义每个变量对应的填充比例尺
scale_mapping <- list(
  vs = scale_fill_simpsons(name = "vs"),
  am = scale_fill_rickandmorty(name = "am"),
  gear = scale_fill_futurama(name = "gear"),
  carb = scale_fill_tron(name = "carb")
)

# 初始化绘图对象
p <- ggplot(temp, aes(y = rnames))

# 循环添加每个变量的图层和比例尺
for (var_name in names(scale_mapping)) {
  p <- p +
    geom_tile(data = filter(temp, key == var_name),
              aes(x = x_pos, fill = value)) +
    scale_mapping[[var_name]] +
    new_scale_fill()
}

# 最后调整轴标签和主题
p <- p +
  scale_x_continuous(breaks = unique(temp$x_pos),
                     labels = unique(temp$key)) +
  labs(x = "变量", y = "车型") +
  theme_minimal() +
  theme(legend.position = "bottom", legend.box = "vertical")

print(p)

这样调整后,你就能得到一个每列有独立离散填充比例尺、共享y轴和统一x轴布局的热图,完美解决你之前遇到的对齐和比例尺冲突问题!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:39:21