使用ggplot绘制基于连续变量的类密度/等高线热力图
实现基于连续变量HPOE的棒球投球等高线热力图
要实现你需要的类密度/等高线热力图,核心是对连续变量HPOE在x-y投球位置网格上进行二维插值,再绘制填充等高线。以下是两种可行方案:
方案一:基于插值的平滑等高线(推荐)
使用akima包对离散投球点的HPOE值做网格插值,得到平滑的连续曲面后,用ggplot2的geom_contour_filled绘制填充等高线,效果最接近目标示例:
library(ggplot2) library(akima) library(dplyr) # 读取数据集 pc_filt <- read.csv("sample_plot_data.csv") # 对HPOE进行x-y网格插值,生成平滑曲面数据 interp_data <- interp( x = pc_filt$x, y = pc_filt$y, z = pc_filt$hpoe, nx = 100, ny = 100, # 数值越高,插值后曲面越平滑 extrap = TRUE # 允许在原始数据范围外插值,适配好球区边界 ) %>% interp2xyz(data.frame = TRUE) %>% rename(hpoe = z) # 绘制可视化 ggplot() + # 填充等高线图层 geom_contour_filled(data = interp_data, aes(x = x, y = y, z = hpoe), bins = 15) + # 绘制好球区边框 geom_segment(y = mean(pc_filt$sz_bot), yend = mean(pc_filt$sz_bot), x = -0.89, xend = 0.89, color = "black", size = 1.25) + geom_segment(y = mean(pc_filt$sz_top), yend = mean(pc_filt$sz_top), x = -0.89, xend = 0.89, color = "black", size = 1.25) + geom_segment(y = mean(pc_filt$sz_bot), yend = mean(pc_filt$sz_top), x = -0.89, xend = -0.89, color = "black", size = 1.25) + geom_segment(y = mean(pc_filt$sz_bot), yend = mean(pc_filt$sz_top), x = 0.89, xend = 0.89, color = "black", size = 1.25) + # 自定义颜色渐变,可根据需求调整 scale_fill_viridis_d(option = "plasma", direction = -1) + # 保持坐标轴比例一致,还原棒球视角 coord_equal() + labs(x = "横向位置", y = "纵向位置", fill = "HPOE") + theme_minimal()
方案二:基于网格汇总的近似等高线
如果不想额外安装akima包,可以用ggplot2内置的stat_summary_2d先对x-y网格内的HPOE做均值汇总,再叠加等高线:
library(ggplot2) # 读取数据集 pc_filt <- read.csv("sample_plot_data.csv") ggplot(pc_filt, aes(x = x, y = y, z = hpoe)) + # 网格汇总HPOE值,生成热力底图 stat_summary_2d(aes(fill = ..value..), bins = 50) + # 叠加白色等高线,增强轮廓感 geom_contour(color = "white", size = 0.5) + # 绘制好球区边框 geom_segment(y = mean(pc_filt$sz_bot), yend = mean(pc_filt$sz_bot), x = -0.89, xend = 0.89, color = "black", size = 1.25) + geom_segment(y = mean(pc_filt$sz_top), yend = mean(pc_filt$sz_top), x = -0.89, xend = 0.89, color = "black", size = 1.25) + geom_segment(y = mean(pc_filt$sz_bot), yend = mean(pc_filt$sz_top), x = -0.89, xend = -0.89, color = "black", size = 1.25) + geom_segment(y = mean(pc_filt$sz_bot), yend = mean(pc_filt$sz_top), x = 0.89, xend = 0.89, color = "black", size = 1.25) + # 自定义颜色渐变,匹配HPOE的取值范围 scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = mean(pc_filt$hpoe)) + coord_equal() + theme_minimal()
为什么之前的方法不符合需求?
stat_density2d:仅计算投球点的密度,不支持自定义连续变量z(即HPOE),所以会报错丢弃z美学,其..level..代表密度值而非HPOE,自然无法匹配需求。geom_tile/geom_raster:需要规整的网格数据,原始离散投球点直接使用会出现大量空白或不均匀瓦片,无法形成平滑的热力效果。stat_summary_hex:对六边形网格内的HPOE做均值汇总,属于分块可视化,无法生成示例中的连续平滑等高线。
内容的提问来源于stack exchange,提问作者ChazC
相关产品推荐
相关产品推荐

