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

在R语言Plotly中添加2D统计密度图的问题求助

解决ggplot转Plotly后stat_density_2d系列图层不显示的问题

问题根源

Plotly对ggplot的stat_density_2d和stat_density_2d_filled图层支持有限,尤其是分面场景下,这类基于实时统计变换的图层无法被ggplotly正确解析转换。此外原代码存在aes映射不规范问题:geom_point的x/y参数未放入aes()内部,导致统计图层无法继承坐标映射。

解决方案:提前计算密度数据,用geom_tile替代统计图层

直接用MASS::kde2d计算2D密度,将结果转为数据框后用geom_tile绘制,Plotly对这类基础图层的兼容性更好。

1. 基础场景(单分面/无分面)代码示例

library(ggplot2)
library(plotly)
library(MASS)

# 假设原始数据框为df
# 提前计算2D密度,lims与后续xlim/ylim保持一致
density_data <- kde2d(df$Var5, df$Var6, n = 100, lims = c(-3, 3, -1.5, 6.5))
density_df <- expand.grid(x = density_data$x, y = density_data$y)
density_df$z <- as.vector(density_data$z)

# 重构ggplot代码
Graph <- ggplot(df, aes(x = Var5, y = Var6,
                        text = paste("Var1:", round(Var1,1), "<br>Var2:", round(Var2,1), "<br>Var3:", round(Var3,1), "<br> Var4:", Var4,
                                     "<br>Var5:", round(Var5,1), "<br>Var6:", round(Var6,1)))) +
    # 绘制密度热力图
    geom_tile(data = density_df, aes(x = x, y = y, fill = z), alpha = 0.3, inherit.aes = FALSE) +
    geom_point(size = .5) +
    scale_fill_gradientn(colours = r, trans = "log") +
    facet_grid(Var7 ~ Var1) +
    geom_path(aes(x, y), data = zone, lwd = 2, col = "black", alpha = .3) +
    xlim(-3, 3) +
    ylim(-1.5, 6.5)

# 转换为Plotly
Graph_Plotly <- ggplotly(Graph, tooltip = "text")

2. 分面场景下的分组密度计算

如果需要每个分面单独计算密度,用dplyr按分面变量分组处理:

library(dplyr)

# 按分面变量Var1、Var7分组计算密度
density_list <- df %>%
    group_by(Var1, Var7) %>%
    group_split() %>%
    lapply(function(sub_df) {
        dens <- kde2d(sub_df$Var5, sub_df$Var6, n = 100, lims = c(-3, 3, -1.5, 6.5))
        expand.grid(x = dens$x, y = dens$y, Var1 = unique(sub_df$Var1), Var7 = unique(sub_df$Var7)) %>%
            mutate(z = as.vector(dens$z))
    })
density_df <- bind_rows(density_list)

# 重构ggplot,此时geom_tile无需设置inherit.aes=FALSE
Graph <- ggplot(df, aes(x = Var5, y = Var6,
                        text = paste("Var1:", round(Var1,1), "<br>Var2:", round(Var2,1), "<br>Var3:", round(Var3,1), "<br> Var4:", Var4,
                                     "<br>Var5:", round(Var5,1), "<br>Var6:", round(Var6,1)))) +
    geom_tile(data = density_df, aes(fill = z), alpha = 0.3) +
    geom_point(size = .5) +
    scale_fill_gradientn(colours = r, trans = "log") +
    facet_grid(Var7 ~ Var1) +
    geom_path(aes(x, y), data = zone, lwd = 2, col = "black", alpha = .3) +
    xlim(-3, 3) +
    ylim(-1.5, 6.5)

Graph_Plotly <- ggplotly(Graph, tooltip = "text")

额外注意事项

  • 确保kde2d的lims参数与xlim/ylim完全一致,避免密度数据被裁剪。
  • 如果需要等高线效果,可将geom_tile替换为geom_contour,同样基于提前计算的密度数据,Plotly能正常解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 08:37:18