如何仅用plotly替代Shiny实现关联热图与散点图联动?
用Plotly + Crosstalk替代Shiny实现热图与散点图联动
没问题!完全可以用Plotly搭配Crosstalk来实现你要的热图点击联动散点图的功能,完全不需要依赖Shiny。这样生成的是纯静态HTML文件,直接就能在浏览器打开,完美绕开shinyapps.io的额度限制,也不用折腾RInno这类打包工具。我给你整理了完整的实现方案:
核心逻辑
- 用
crosstalk的消息订阅/发布机制实现两个Plotly图表的通信,不需要服务器端支持 - 给热图的每个单元格绑定对应的变量对信息,点击时把变量名传递给散点图
- 散点图监听消息,动态切换x/y变量并重新计算回归线
完整代码实现
library(plotly) library(crosstalk) library(htmltools) # 准备数据,替换成你的大型数据集即可 correlation <- round(cor(mtcars), 3) nms <- names(mtcars) # 创建共享数据对象,用于传递点击选择的变量 shared_data <- SharedData$new(data.frame(selected_x = character(), selected_y = character())) # 绘制关联热图 heatmap_plot <- plot_ly( x = nms, y = nms, z = correlation, type = "heatmap", # 为每个单元格绑定对应的变量对,用分隔符区分 customdata = outer(nms, nms, paste, sep = "|") ) %>% layout(xaxis = list(title = ""), yaxis = list(title = "")) %>% # 添加点击事件的JavaScript逻辑,发布选中的变量对 onRender(" function(el) { el.addEventListener('plotly_click', function(event) { const point = event.points[0]; const [xVar, yVar] = point.customdata.split('|'); // 通过Crosstalk发布消息,传递选中的变量 Crosstalk.publish('selected_vars', {x: xVar, y: yVar}); }); } ") # 绘制响应式散点图(含回归线) scatter_plot <- plot_ly( data = mtcars, x = ~mpg, y = ~mpg, # 初始占位值 type = "scatter", mode = "markers", # 保留原始数据用于后续计算 source = mtcars ) %>% add_lines(y = ~fitted(lm(mpg ~ mpg, data = mtcars))) %>% layout(showlegend = FALSE) %>% # 监听Crosstalk的消息,动态更新图表 onRender(" function(el) { // 监听选中变量的消息 Crosstalk.subscribe('selected_vars', function(vars) { const xVar = vars.x; const yVar = vars.y; const rawData = Plotly.d3.select(el).data()[0].raw; // 更新散点图数据 const scatterTrace = el.data[0]; scatterTrace.x = rawData[xVar]; scatterTrace.y = rawData[yVar]; // 计算并更新回归线 const x = rawData[xVar]; const y = rawData[yVar]; const xMean = x.reduce((a, b) => a + b, 0) / x.length; const yMean = y.reduce((a, b) => a + b, 0) / y.length; const slope = x.reduce((sum, xi, i) => sum + (xi - xMean) * (y[i] - yMean), 0) / x.reduce((sum, xi) => sum + (xi - xMean) ** 2, 0); const intercept = yMean - slope * xMean; const yhat = x.map(xi => slope * xi + intercept); const lineTrace = el.data[1]; lineTrace.x = x; lineTrace.y = yhat; // 更新坐标轴标题 Plotly.update(el, [scatterTrace, lineTrace], { xaxis: {title: xVar}, yaxis: {title: yVar} }); }); } ") # 组合图表并生成可浏览的HTML页面 final_page <- tagList( crosstalkLibs(), # 加载Crosstalk依赖 div( style = "display: flex; gap: 2rem; padding: 1rem;", div(heatmap_plot, style = "flex: 1;"), div(scatter_plot, style = "flex: 1;") ) ) # 直接在浏览器打开页面 browsable(final_page) # 或者保存为独立HTML文件,方便分享 # saveWidget(final_page, "linked_heatmap_scatter.html", selfcontained = TRUE)
使用说明
- 把代码里的
mtcars替换成你的大型数据集,确保变量名正确 - 运行代码后会自动在浏览器打开联动页面,点击热图的任意单元格,右侧散点图会自动切换为对应变量的散点图+回归线
- 如果需要分享给其他人,取消最后一行的注释,运行
saveWidget()生成独立的HTML文件,这个文件可以直接发给同事或者放在公司内网,不需要任何服务器支持
效果展示

内容的提问来源于stack exchange,提问作者J.Con
相关产品推荐
相关产品推荐

