如何对时间线上的点插值以绘制浓度随时间变化的平滑色块图
R ggplot实现X物质浓度时间序列水平插值平滑图
原代码使用geom_tile(interpolate = T)是图形渲染层面的双向插值,会同时在时间轴、样本位置两个方向做平滑,不符合仅沿时间方向水平插值的需求,同时y轴默认显示数值刻度,未映射到样本名称。以下是两种可行实现方案:
方案1:调整geom_tile参数快速实现
通过固定色块高度避免y轴方向的插值,仅保留时间方向的平滑效果,代码改动量最小:
library(tidyverse) # 生成测试数据 df <- data.frame(Concentration = rnorm(30), Position = rep(c(0, 1), 15), Sample = rep(c("A", "B"), 15), Date = seq.Date(as.Date("2020-01-01"), as.Date("2020-01-30"), "days")) df %>% ggplot(aes(x = Date, y = Position)) + # 固定色块高度为0.9,避免上下两个样本的色块互相插值 geom_tile(aes(fill = Concentration), height = 0.9, interpolate = T) + # 替换y轴刻度为样本名 scale_y_continuous(breaks = c(0, 1), labels = c("A", "B")) + labs(x = "Day", y = "Sample", fill = "X物质浓度") + # 可选:调整为更易读的渐变色 scale_fill_viridis_c()
该方案无需修改原始数据,适合快速出图场景。
方案2:数据层面先插值再绘图(平滑效果更可控)
如果需要自定义平滑精度,可先对每个样本的浓度时间序列做高密度插值后再绘图:
library(tidyverse) df <- data.frame(Concentration = rnorm(30), Position = rep(c(0, 1), 15), Sample = rep(c("A", "B"), 15), Date = seq.Date(as.Date("2020-01-01"), as.Date("2020-01-30"), "days")) # 按样本分组做时间插值,时间密度可按需调整,示例为间隔6小时一个插值点 interp_df <- df %>% group_by(Sample, Position) %>% summarise( Date = seq.Date(min(Date), max(Date), by = "6 hours"), # 线性插值,替换为splinefun可实现样条插值,平滑度更高 Concentration = approx(Date, Concentration, xout = Date)$y, .groups = "drop" ) interp_df %>% ggplot(aes(x = Date, y = Position)) + geom_tile(aes(fill = Concentration), height = 0.9) + scale_y_continuous(breaks = c(0, 1), labels = c("A", "B")) + labs(x = "Day", y = "Sample", fill = "X物质浓度") + scale_fill_viridis_c()
该方案平滑效果完全由数据插值逻辑控制,不会出现渲染层异常插值问题,适合对精度要求高的场景。
内容的提问来源于stack exchange,提问作者Lee1010
相关产品推荐
相关产品推荐

