如何用ggplot2绘制按Hypocretin浓度列归一化的平滑热力图?
解决方案:同时实现列归一化与平滑的热力图
要同时满足按hypocretin浓度列归一化频率和平滑效果,可以通过「先分箱计算归一化密度,再对密度进行二维平滑,最后绘制热力图」的流程实现。以下是完整的ggplot2代码方案,包含模拟数据、预处理、平滑和绘图步骤:
1. 加载依赖包与模拟数据
先模拟一组hypocretin与BMI的关联数据(你可以替换成自己的真实数据):
library(tidyverse) library(mgcv) # 用于非线性平滑模型 # 模拟真实数据分布 set.seed(123) n <- 1000 hypocretin <- rnorm(n, mean = 20, sd = 5) BMI <- 22 + 0.3*(hypocretin - 20) + rnorm(n, sd = 3) df <- tibble(hypocretin, BMI)
2. 按hypocretin分箱,计算归一化BMI频率
先将hypocretin分成若干区间,在每个区间内计算BMI的密度并归一化(确保每个区间的频率总和为1):
# 对hypocretin分箱(可根据数据调整breaks数量) df_processed <- df %>% mutate(hypo_bin = cut(hypocretin, breaks = 20, labels = FALSE)) %>% group_by(hypo_bin) %>% mutate(hypo_center = mean(hypocretin)) %>% # 用箱中心代表该区间的浓度值 ungroup() # 计算每个分箱内BMI的归一化密度 density_df <- df_processed %>% group_by(hypo_bin, hypo_center) %>% summarise( # 生成覆盖BMI范围的序列 bmi_seq = seq(min(BMI, na.rm = TRUE), max(BMI, na.rm = TRUE), length.out = 50), # 计算BMI的核密度 dens = density(BMI, from = min(bmi_seq), to = max(bmi_seq), n = 50)$y, # 归一化:将密度积分调整为1(近似为密度*步长的总和) dens_norm = dens / sum(dens * diff(bmi_seq)[1]) ) %>% ungroup()
3. 对归一化密度进行二维平滑
使用广义可加模型(GAM)对归一化后的密度进行非线性平滑,拟合hypocretin与BMI之间的连续趋势:
# 拟合GAM平滑模型 smooth_model <- gam(dens_norm ~ s(hypo_center, bmi_seq), data = density_df) # 生成高分辨率的预测网格 pred_grid <- expand.grid( hypo_center = seq(min(df$hypocretin), max(df$hypocretin), length.out = 100), bmi_seq = seq(min(df$BMI), max(df$BMI), length.out = 100) ) # 预测平滑后的归一化密度,确保非负(密度不能为负) pred_grid$dens_smooth <- pmax(predict(smooth_model, newdata = pred_grid), 0)
4. 绘制平滑热力图
用geom_raster结合interpolate = TRUE实现平滑的颜色过渡,同时展示归一化后的频率:
ggplot(pred_grid, aes(x = hypo_center, y = bmi_seq, fill = dens_smooth)) + geom_raster(interpolate = TRUE) + # 开启插值实现平滑效果 scale_fill_viridis_c(name = "Normalized\nFrequency") + # 用viridis色阶提升可读性 labs( x = "Hypocretin Concentration", y = "BMI", title = "Smoothed Normalized Frequency of BMI by Hypocretin" ) + theme_minimal()
关键逻辑说明
- 列归一化:通过分箱hypocretin,在每个箱内单独计算BMI的密度并归一化,确保每个浓度对应的BMI频率总和为1,解决了中间浓度数据稀疏导致的趋势不明显问题。
- 平滑效果:先用GAM模型拟合归一化密度的二维趋势,再通过
geom_raster(interpolate = TRUE)实现颜色的平滑过渡,兼顾了趋势的连续性和图表可读性。
内容的提问来源于stack exchange,提问作者Jingru
相关产品推荐
相关产品推荐

