如何在独立窗口显示带plotly-resampler动态重采样的Dash图表?
问题
我有一个包含约4200万样本的500个Parquet文件数据集,用Dask读取数据后,通过简单下采样用Plotly绘图,目前运行正常。我希望在独立窗口(类似Matplotlib的窗口形式)中展示交互式图表,而非网页标签或Jupyter环境,之前已经用QWebEngineView实现了静态Plotly图的窗口展示。
因为数据集太大,我想使用plotly-resampler库实现基于缩放层级的动态重采样,但这个库依赖Dash。尝试将FigureResampler生成的图表传入原窗口展示代码后,图表只保留初始采样结果,缩放时无法动态更新重采样。
请问有没有办法在独立窗口中展示Dash图表,同时保留Dash的动态交互功能?
相关代码示例
原静态Plotly图窗口展示代码
# 原静态Plotly图窗口展示代码 import dask.dataframe as dd import plotly.graph_objects as go def show_in_window(fig): import sys, os import plotly.offline from PyQt5.QtCore import QUrl from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtWidgets import QApplication plotly.offline.plot(fig, filename='temp.html', auto_open=False) app = QApplication(sys.argv) web = QWebEngineView() file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "temp.html")) web.load(QUrl.fromLocalFile(file_path)) web.show() sys.exit(app.exec_()) def create_plot(df,x_param,y_param): fig.add_trace(go.Scattergl(x = df[x_param] , y = df[y_param], mode ='markers')) fig = go.Figure() ddf = dd.read_parquet("results_parq/*.parquet") create_data_for_plot(ddf,'t','reg',1) fig.update_layout(showlegend=False) show_in_window(fig)
尝试的动态重采样代码
fig = FigureResampler(go.Figure()) ddf = dd.read_parquet("results_parq/*.parquet") create_data_for_plot(ddf,'t','reg',1) show_in_window(fig)
解决方案
方法1:PyQt嵌入Dash本地服务
plotly-resampler的动态交互依赖Dash的回调机制,静态HTML文件无法触发这些回调。因此需要在PyQt窗口中启动一个本地Dash服务,再用QWebEngineView加载服务URL,以此保留动态交互功能。
示例代码:
import sys import threading import dask.dataframe as dd import plotly.graph_objects as go from plotly_resampler import FigureResampler from dash import Dash, dcc, html from PyQt5.QtCore import QUrl from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtWidgets import QApplication def run_dash_app(app, port=8050): # 后台线程启动Dash服务,避免阻塞PyQt主线程 app.run_server(port=port, debug=False, use_reloader=False) def show_dash_in_window(dash_app, port=8050): # 启动Dash服务线程 threading.Thread(target=run_dash_app, args=(dash_app, port), daemon=True).start() # 创建并显示PyQt窗口 app = QApplication(sys.argv) web = QWebEngineView() web.load(QUrl(f"http://localhost:{port}")) web.show() sys.exit(app.exec_()) def create_resampled_plot(ddf, x_param, y_param): # 创建可重采样图表 fig = FigureResampler(go.Figure()) # 获取数据(若数据量过大,可改用plotly-resampler的Dask懒加载支持) df_sample = ddf.compute() fig.add_trace( go.Scattergl(x=df_sample[x_param], y=df_sample[y_param], mode='markers'), hf_x=df_sample[x_param], hf_y=df_sample[y_param] ) # 生成Dash应用并注册重采样回调 dash_app = Dash(__name__) dash_app.layout = html.Div([dcc.Graph(figure=fig)]) fig.register_update_graph_callback(dash_app) return dash_app # 主逻辑 if __name__ == "__main__": ddf = dd.read_parquet("results_parq/*.parquet") dash_app = create_resampled_plot(ddf, 't', 'reg') show_dash_in_window(dash_app)
方法2:客户端离线重采样(限轻量场景)
部分版本的plotly-resampler支持生成包含客户端重采样逻辑的HTML文件,无需依赖Dash服务。可尝试用write_html生成交互HTML后加载:
def show_resampled_in_window(fig): import sys, os from PyQt5.QtCore import QUrl from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtWidgets import QApplication # 生成带客户端重采样逻辑的HTML fig.write_html("temp_resampled.html", include_plotlyjs="cdn") app = QApplication(sys.argv) web = QWebEngineView() file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "temp_resampled.html")) web.load(QUrl.fromLocalFile(file_path)) web.show() sys.exit(app.exec_()) # 使用示例 fig = FigureResampler(go.Figure()) df_sample = ddf.compute() fig.add_trace( go.Scattergl(x=df_sample['t'], y=df_sample['reg'], mode='markers'), hf_x=df_sample['t'], hf_y=df_sample['reg'] ) show_resampled_in_window(fig)
注意:该方法的客户端重采样能力有限,超大规模数据场景下,流畅度不如Dash服务端重采样。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

