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

如何在ggplot2热力图/栅格图中高亮感兴趣区域(无需terra包)

问题描述

我需要在ggplot2绘制的热力图/栅格图中标记感兴趣区域,数据是包含三个变量的连续数据(非空间数据)。目前已通过terra包实现了用多边形标记自定义阈值区域的方案,但希望找到无需依赖terra包的更简洁优雅的替代方法。

原实现代码:

library(ggplot2)
library(dplyr)
library(terra)

data("faithfuld")

# rasterize the data with terra
ncol <- faithfuld |> distinct(waiting) |> nrow()
nrow <- faithfuld |> distinct(eruptions) |> nrow()
xmin <- faithfuld$waiting |> min()
xmax <- faithfuld$waiting |> max()
ymin <- faithfuld$eruptions |> min()
ymax <- faithfuld$eruptions |> max()

faithful_vec <- vect(faithfuld, geom = c("waiting", "eruptions"))

r1 <- rast(ncol=ncol, nrow=nrow, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
r1 <- rasterize(faithful_vec, r1, "density", mean)

# filter values to highlight
r1[r1 < 0.025] <- NA

# convert to polygon and grab geometry
r2 <- as.polygons(r1) |> 
  geom() |> 
  as_tibble()

ggplot() +
  geom_raster(data = faithfuld, aes(waiting, eruptions, fill = density), interpolate = TRUE) +
  ## highlighted area ##
  geom_polygon(data = r2, aes(x, y, group = part), color = "white", fill = "transparent") +
  scale_fill_viridis_c()

当前实现效果:
热力图标记效果


替代方案(无需terra包)

可以利用R基础包的contourLines()函数提取阈值对应的轮廓线,再转换为数据框后用geom_polygon()绘制标记区域,仅依赖ggplot2和dplyr:

library(ggplot2)
library(dplyr)
library(purrr)

data("faithfuld")

# 提取阈值0.025对应的轮廓线
contour_data <- contourLines(
  x = unique(faithfuld$waiting),
  y = unique(faithfuld$eruptions),
  z = matrix(faithfuld$density, nrow = length(unique(faithfuld$eruptions))),
  levels = 0.025
)

# 将轮廓线列表转换为可用于ggplot的数据框
contour_df <- contour_data |>
  map_dfr(~tibble(x = .x$x, y = .x$y), .id = "piece")

ggplot() +
  geom_raster(data = faithfuld, aes(waiting, eruptions, fill = density), interpolate = TRUE) +
  # 绘制标记多边形
  geom_polygon(data = contour_df, aes(x, y, group = piece), color = "white", fill = "transparent") +
  scale_fill_viridis_c()

方案说明

  • contourLines()根据输入的x/y网格和z值,直接提取指定阈值的轮廓线坐标,返回列表格式结果
  • 用map_dfr()将列表转换为数据框,同时为不同轮廓块添加分组标识,确保geom_polygon()能正确识别独立区域
  • 最终效果与原terra方案完全一致,且仅依赖tidyverse核心包

如果不想引入purrr,可以用基础R代码完成数据转换:

# 基础R转换方法
contour_df <- do.call(rbind, lapply(seq_along(contour_data), function(i) {
  cl <- contour_data[[i]]
  data.frame(x = cl$x, y = cl$y, piece = as.character(i))
}))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 12:01:02