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

如何叠加两类六边形热力图:物种引入概率与已占领区域展示

解决叠加双六边形热力图的填充冲突问题

我懂你的困扰——你想在同一张图里同时展示物种引入概率的热力分布,以及已经被占领的黑色六边形区域,但默认情况下ggplot的填充比例尺只能有一个,第二个scale_fill会直接覆盖第一个的设置。这里有两种实用的解决方法:

方法1:用固定颜色覆盖已占领区域(无需额外包)

这个思路很直接:先绘制引入概率的热力图,再在上面叠加仅包含已占领区域的黑色六边形。因为我们给这些六边形设置固定填充色,不会用到映射的fill属性,所以不会和第一个热力图的比例尺冲突。

完整代码:

set.seed(123) # 确保结果可复现
df <- data.frame(latitude = rep(seq(1,10,1),10), 
                 longitude = rep(1:10, each=10), 
                 already_there = rbinom(100,1,0.1), 
                 introduction_probability = rbinom(100,100,0.5)/100)

library(ggplot2)

ggplot(data = df) +
  # 第一步:绘制引入概率的热力六边形
  stat_summary_hex(aes(x = longitude, y = latitude, z = introduction_probability),
                   binwidth = c(2,2)) +
  scale_fill_gradient2(mid="yellow", high="red", 
                       breaks=seq(0,1,0.25), limits=c(0,1),
                       name = "Introduction Probability") +
  # 第二步:叠加已占领区域的黑色六边形(仅过滤出已占领的行)
  geom_hex(data = subset(df, already_there == 1),
           aes(x = longitude, y = latitude),
           binwidth = c(2,2), # 必须和前面的binwidth一致,保证对齐
           fill = "black") +
  labs(title = "Species Introduction Probability & Occupied Zones",
       x = "Longitude", y = "Latitude")

方法2:用ggnewscale添加多个填充比例尺(支持双图例)

如果你想让已占领区域的黑色也单独显示在图例里,可以用ggnewscale包——它专门解决ggplot中同一美学属性需要多个比例尺的问题。

完整代码:

# 先安装包(仅第一次需要)
install.packages("ggnewscale")

library(ggplot2)
library(ggnewscale)

set.seed(123)
df <- data.frame(latitude = rep(seq(1,10,1),10), 
                 longitude = rep(1:10, each=10), 
                 already_there = rbinom(100,1,0.1), 
                 introduction_probability = rbinom(100,100,0.5)/100)

ggplot(data = df) +
  # 第一个图层:引入概率热力图
  stat_summary_hex(aes(x = longitude, y = latitude, z = introduction_probability),
                   binwidth = c(2,2)) +
  scale_fill_gradient2(mid="yellow", high="red", 
                       breaks=seq(0,1,0.25), limits=c(0,1),
                       name = "Introduction Probability") +
  # 关键:开启新的填充比例尺上下文
  new_scale_fill() +
  # 第二个图层:已占领区域的六边形
  stat_summary_hex(aes(x = longitude, y = latitude, z = already_there),
                   binwidth = c(2,2)) +
  scale_fill_gradient2(low = NA, high = "black", # 仅显示已占领(z=1)的黑色
                       breaks = c(0,1), limits = c(0,1),
                       name = "Already Occupied") +
  labs(title = "Dual Hexbin Heatmap: Probability & Occupancy",
       x = "Longitude", y = "Latitude")

为什么你的原代码不行?

ggplot2的设计逻辑是:同一个美学属性(比如fill)只能绑定一个比例尺。当你添加第二个scale_fill_gradient2时,它会完全替换掉第一个的设置,导致只有最后一个比例尺生效。上面两种方法要么避开了重复映射fill,要么用工具包扩展了ggplot的比例尺能力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:28:25