次のことを行うのに非常に苦労しています。さまざまなコンテナーに表示するために CSS でフォーマットされたダッシュ アプリケーションがあります。 「hexgrid-1-container」というラベルの付いたコンテナーが最大のコンテナーであり、他のコンテナーはより小さく、その周りに編成されています。ダッシュ アプリを更新して、別のコンテナー内の図/グラフィックをクリックすると、前の図が「hexgrid-1-container」にあった場所にその図/グラフィックが「hexgrid-1-container」に表示されるようにしたいです。コンテナーはより小さいコンテナーに表示されます。 。
次のようなダッシュ アプリケーションがあります:
インポートダッシュ ダッシュ_コア_コンポーネントを dcc としてインポートします ダッシュ_html_componentsをHTMLとしてインポート from dump.dependency import 入力、出力、状態 jupyter_dash から JupyterDash をインポート pxとしてplotly.expressをインポートします そのままplotly.graph_objectsをインポートします パンダをPDとしてインポートする sqlite3をインポートする ロケールをインポートする numpyをnpとしてインポート インポートplotly.figure_factoryをffとして pxとしてplotly.expressをインポートします # 書式設定のロケールを設定する locale.setlocale(locale.LC_ALL, '') app = ダッシュ.ダッシュ(__name__) app.layout = html.Div(className= 'コンテナ ガラス', Children=[ html.Div(className='hexgrid-1-container', style={'border': '1px ソリッドブラック'}, Children=[ dcc.Graph(id='hexgrid-1', style={"height": "75%", "width": "100%"}, className='hexgrid1') ])、 html.Div(className='hexgrid-2-container', style={'border': '1px ソリッド ブラック'}, Children=[ dcc.Graph(id='hexgrid-2', style={"height": "100%", "width": "100%"}, className='hexgrid2') ])、 html.Div(className='base-plot-container', style={'border': '1px ソリッドブラック'}, Children=[ dcc.Graph(id='base-plot', style={"高さ": "100%", "幅": "100%"}) ])、 html.Div(className='us-map-container', style={'border': '1px ソリッドブラック'}, Children=[ dcc.Graph(id='us-map-graph', style={"高さ": "100%", "幅": "100%"}) ])、 html.Div(className='fifth-container', style={'border': '1px ソリッドブラック'}, Children=[ # dcc.Graph(id='us-map-graph', style={"高さ": "100%", "幅": "100%"}) #html.H2("5 番目のコンテナ") ])、 html.Div(className='sixth-container', style={'border': '1px ソリッドブラック'}, Children=[ # dcc.Graph(id='us-map-graph', style={"高さ": "100%", "幅": "100%"}) #html.H2("6 番目のコンテナ") ]) ]) @app.callback( Output('hexgrid-1', 'figure'), 入力('hexgrid-1', 'id') ) def render_hexgrid_1(_): # 新しいデータベース接続を開く conn = sqlite3.connect(r"C:\Users\HituJani\Downloads\txns.db") # トランザクションテーブルのすべての列を取得します クエリ = '' PRAGMA table_info(トランザクション) 「」 # データを取得する データ = pd.read_sql_query(クエリ, conn) # 関連する列をフィルタリングして除外します。すべての列が必要な場合は、この手順をスキップできます。 関連列 = データ[データ['名前'].isin(['TranType', 'MessageTypeIdentifier', 'MerchantType', 'IResponseCode'])] # 列名を使用した 16 進グリッドの作成 Lot_data = go.Scatter(x=relevant_columns.index, y=relevant_columns['name'], text=relevant_columns['name'], マーカー=dict(シンボル='六角形', サイズ=30), モード='マーカーテキスト') layout = go.Layout(title="カテゴリを選択") return go.Figure(data=[プロットデータ], レイアウト=レイアウト) @app.callback( Output('hexgrid-2', 'figure'), 出力('hexgrid-2', 'スタイル'), 入力('hexgrid-1', 'clickData') ) def render_hexgrid_2(clickData): # 新しいデータベース接続を開く conn = sqlite3.connect(r"C:\Users\HituJani\Downloads\txns.db") clickData が None の場合: return go.Figure(), {"表示": "なし"}それ以外: カテゴリ = clickData['ポイント'][0]['テキスト'] # トランザクションテーブルのすべての列を取得します クエリ = '' PRAGMA table_info(トランザクション) 「」 # データを取得する データ = pd.read_sql_query(クエリ, conn) # 関連する数値特徴列をフィルタリングして除外する 関連列 = データ[データ['名前'].isin(['取引額', '未払い額', '現在の残高', 'TotalOutStgAuthAmt'])] # 球の表面にランダムな点を生成する phi = np.random.uniform(0, np.pi, len(relevant_columns)) theta = np.random.uniform(0, 2*np.pi, len(relevant_columns)) x = np.cos(シータ) * np.sin(ファイ) y = np.sin(θ) * np.sin(ファイ) z = np.cos(ファイ) # 球マーカーを使用して 3D 散布図を作成する 散布 = go.Scatter3d( x=x、 y=y、 z=z、 mode='マーカーテキスト', マーカー=dict( サイズ=12、 color=np.arange(len(関連列)), colorscale='ウィリディス', シンボル='円'、 不透明度=0.8 )、 text=relevant_columns['名前']、 hoverinfo='テキスト' ) # メッシュを使用してワイヤーフレーム球を作成する u = np.linspace(0, 2 * np.pi, 100) v = np.linspace(0, np.pi, 100) x_sphere = np.outer(np.cos(u), np.sin(v)) y_sphere = np.outer(np.sin(u), np.sin(v)) z_sphere = np.outer(np.ones(np.size(u)), np.cos(v)) sphere = go.Mesh3d(x=x_sphere.ravel(), y=y_sphere.ravel()、 z=z_sphere.ravel()、 不透明度=0.1、 color='シアン') # 散布図とワイヤーフレームを 1 つの図に結合します fig = go.Figure(data=[散乱, 球]) fig.update_layout( margin=dict(l=0, r=0, b=0, t=0), シーン=dict( xaxis=dict(title=None、visible=False)、 yaxis=dict(title=None、visible=False)、 zaxis=dict(title=None、visible=False)、 )、 template='plotly_dark' ) return fig、{"高さ": "50vh"、"幅": "100%"、"表示": "インラインブロック"} # プロットを更新し、球を強調表示し、ドリルダウンを有効にするコールバック関数を定義します。 @app.callback( Output('ベースプロット', '図'), 入力('hexgrid-2', 'clickData'), State('hexgrid-1', 'clickData') ) def update_base_plot(clickData_hexgrid_2, clickData_hexgrid_1): 試す: # 新しいデータベース接続を開く conn = sqlite3.connect(r"C:\Users\HituJani\Downloads\txns.db") カテゴリ = clickData_hexgrid_1['ポイント'][0]['テキスト'] Numerical_feature = clickData_hexgrid_2['ポイント'][0]['テキスト'] # 選択したカテゴリと数値特徴に基づいて集計データを取得する SQL クエリ クエリ = f''' SELECT {category}、WeekOfMonth、SUM({numerical_feature}) AS TotalAmount FROMトランザクション {カテゴリ}ごとにグループ化、月の週 合計金額 DESC で注文 「」 # データベースからデータを取得します df_base = pd.read_sql(クエリ, conn) # データベース接続を閉じる conn.close() # 合計列の書式設定 df_base['TotalAmount'] = df_base['TotalAmount'].apply(lambda x: locale.currency(x, grouping=True)) # 球マーカーを使用した 3D 散布図の作成 fig = go.Figure() # WeekOfMonth 値のカラースケールを定義する カラースケール = [ [0, '青'], # 第 1 週: 青 [0.25, 'purple']、# 第 2 週: 紫 [0.5, 'darkorange']、# 第 3 週: ダークオレンジ [0.75、'黄色']、# 第 4 週: 黄色 [1、「ピンク」] # 第 5 週: ピンク ] # 散布図トレースを追加します fig.add_trace( go.Scatter3d( x=df_base[カテゴリ]、 y=df_base['WeekOfMonth'].astype(int), z=df_base['合計金額'], mode='マーカーテキスト', マーカー=dict( size=5, # マーカーのサイズを調整して小さくします symbol='circle', # 球には「circle」シンボルを使用します color=df_base['月の週']、 カラースケール=カラースケール、 )、 textposition='上部中央', hovertemplate=( f"<b>{カテゴリ}</b>: %{{x}}<br>" "合計金額: %{z}
" "月の週: %{y}
" ) ) ) # y 軸範囲を動的に設定する y_max = df_base['WeekOfMonth'].max() fig.update_layout( シーン=dict( xaxis=dict( タイトル=カテゴリー、 title_font=dict(size=14, color='darkorange'), visible=False # X 軸を非表示にする )、 yaxis=dict( title='月の週', title_font=dict(size=14, color='purple'), ティックモード='配列', tinyvals=[0.5, 1.5, 2.5, 3.5, 4.5, 5.5], tictext=['1', '2', '3', '4', '5'], # 目盛りラベルを 1, 2, 3, 4, 5 として表示します], visible=False # y 軸を非表示にする )、 zaxis=dict( title=f'合計 {数値機能} ($)', title_font=dict(size=14, color=' yellow'), autorange='反転', visible=False # Z 軸を非表示にする )、 )、 xaxis=dict( type='カテゴリ', ティックモード='リニア'、 目盛り=45、 automargin=True、 visible=False # X 軸のラベルを非表示にする )、 margin=dict(l=10, r=10, t=10, b=10), # b の値を増やして表示ウィンドウを拡大します template='plotly_dark', ) イチジクを返す e としての例外を除く: print(f"エラー: {e}") go.Figure() を返す @app.callback( Output('us-map-graph', 'figure'), Output('us-map-graph', 'style'), 入力('ベースプロット', 'クリックデータ'), State('hexgrid-1', 'clickData'), State('hexgrid-2', 'clickData') ) def display_transaction_amount(base_plot_click_data, hexgrid_1_clickData, hexgrid_2_clickData): 試す: # hexgrid-1 と hexgrid-2 からのデータが利用可能かどうかを確認します hexgrid_1_clickData が None または hexgrid_2_clickData が None の場合: # 空の図を返し、マップを非表示にします return go.Figure(), {"表示": "なし"} # hexgrid-1 から選択したカテゴリを取得し、hexgrid-2 から数値特徴を取得します selected_category = hexgrid_1_clickData['ポイント'][0]['テキスト'] Numerical_feature = hexgrid_2_clickData['ポイント'][0]['テキスト'] # 選択したサブカテゴリをbase_plot_click_dataから取得します selected_subcategory = なし Base_plot_click_data が None でない場合: selected_subcategory = Base_plot_click_data['points'][0]['x'] # 新しいデータベース接続を開く conn = sqlite3.connect(r"C:\Users\HituJani\Downloads\txns.db") # 選択したカテゴリ、サブカテゴリ、および数値特徴の状態別にトランザクション データを取得する SQL クエリ クエリ = f''' SELECT StateCode, {selected_category}, SUM({numerical_feature}) AS TotalTransactionAmount FROMトランザクション WHERE {選択されたカテゴリ} = ? GROUP BY StateCode、{selected_category} 「」 # クエリを実行し、結果を DataFrame にフェッチします state_data = pd.read_sql(query, conn, params=(selected_subcategory,)) # データベース接続を閉じる conn.close() # フィルタリングされたデータを使用してコロプレス マップを作成する fig = px.コロプレス( データフレーム=状態データ、 locationmode='米国の州', 場所='州コード', スコープ='米国'、 color='合計取引金額', hover_data={'StateCode': True, 'TotalTransactionAmount': ':$,f'}, color_continuous_scale='レッド', ラベル={'TotalTransactionAmount': '合計トランザクション金額'}, template='plotly_dark' ) fig.update_traces( hovertemplate="<b>%{customdata[0]}</b><br>" "<b>TotalTransactionAmount</b>: $%{customdata[1]:,.2f}<br>", Customdata=list(zip(state_data['StateCode'], state_data['TotalTransactionAmount'])) ) fig.update_layout( title_text=f'カテゴリ: {selected_category}、サブカテゴリ: {selected_subcategory}' の州別合計取引額', title_xanchor='センター', title_font=dict(size=12), title_x=0.5、 geo=dict(scope='usa'), ) # Figureを返し、表示スタイルをブロック(可視)に設定します return fig、{"表示": "ブロック"} e としての例外を除く: print(f"エラー: {e}") return go.Figure(), {"表示": "なし"} __name__ == '__main__'の場合: app.run_server(debug=True、use_reloader=False)
さらに、私はこの格式化ネット页のcssファイルを持っています:
/* スタイル.css */ 。容器 { 表示: グリッド; グリッド テンプレート行: 1fr 1fr 1fr; グリッド テンプレート列: 1fr 1fr 1fr; グリッド列ギャップ: 15px; グリッド行ギャップ: 15px; 背景画像: url("https://plainbackground.com/plain1024/383c3d.png"); 背景サイズ: 100%; 背景位置: グリッド ce; } .hexgrid-1-container { /* グリッド領域: 1/1/3/3; */ グリッド行: スパン 2; グリッド列: スパン 2; パディング: 2px 2px 2px 2px; ボーダー: 1px ソリッド hsl(176, 87%, 7%, 0.6); 境界半径: 10px; ボックスシャドウ: rgba(250, 118, 3, 0.4) -5px 5px, rgba(250, 118, 3, 0.3) -10px 10px, rgba(250, 118, 3, 0.2) -15px 15px; バックグラウンド: hsla(0, 7%, 11%, 0.9); 位置: 相対的; } .hexgrid-2-container { グリッド領域: 1/3/2/4; パディング: 3レム 4レム 4レム; 幅: 70%; ボーダー: 1px ソリッド hsl(176, 87%, 7%, 0.6); 境界半径: 10px; ボックスシャドウ: rgba(250, 118, 3, 0.4) -5px 5px, rgba(250, 118, 3, 0.3) -10px 10px, rgba(250, 118, 3, 0.2) -15px 15px; バックグラウンド: hsl(0, 7%, 11%, 0.9); 位置: 相対的; } .base-plot-container { /* ここにベースプロットコンテナのカスタムスタイルを追加します */ グリッド領域: 2/3/3/4; パディング: 3レム 4レム 4レム; 幅: 70%; ボーダー: 1px ソリッド hsl(176, 87%, 7%, 0.6); 境界半径: 10px; ボックスシャドウ: rgba(250, 118, 3, 0.4) -5px 5px, rgba(250, 118, 3, 0.3) -10px 10px, rgba(250, 118, 3, 0.2) -15px 15px; バックグラウンド: hsl(0, 7%, 11%, 0.9); 位置: 相対的; } .us-map-container { グリッド領域: 3/3/4/4; パディング: 3レム 4レム 4レム; 幅: 70%; /* 位置: 固定; */ ボーダー: 1px ソリッド hsl(176, 87%, 7%, 0.6); 境界半径: 10px; ボックスシャドウ: rgba(250, 118, 3, 0.4) -5px 5px, rgba(250, 118, 3, 0.3) -10px 10px, rgba(250, 118, 3, 0.2) -15px 15px; バックグラウンド: hsl(0, 7%, 11%, 0.9); 位置: 相対的; } .fifth-container { グリッド領域: 3/2/4/3; ボーダー: 1px ソリッド hsl(176, 87%, 7%, 0.6); 境界半径: 10px; ボックスシャドウ: rgba(250, 118, 3, 0.4) -5px 5px, rgba(250, 118, 3, 0.3) -10px 10px, rgba(250, 118, 3, 0.2) -15px 15px; バックグラウンド: hsl(0, 7%, 11%, 0.9); 位置: 相対的; } .sixth-container { グリッド領域: 3/1/4/2; ボーダー: 1px ソリッド hsl(176, 87%, 7%, 0.6); 境界半径: 10px; ボックスシャドウ: rgba(250, 118, 3, 0.4) -5px 5px, rgba(250, 118, 3, 0.3) -10px 10px, rgba(250, 118, 3, 0.2) -15px 15px; バックグラウンド: hsl(0, 7%, 11%, 0.9); 位置: 相対的; }
私は関数の更新を試みていますが、それほど大きくはなく、かなりの困難を抱えています。この機能を実現するための最も直接的な方法は何でしょうか?
P粉2524239062024-02-27 15:34:56
コールバックを作成してクリック イベントをリッスンし、グラフィックの位置を交換し、グラフィックを更新された位置に戻すことができます。ユースケースに応じてクリックロジックを設定する必要があります。次のようなものを実装できます:
@app.callback( Output('hexgrid-1-container', 'children'), Output('hexgrid-2-container', 'children'), 入力('hexgrid-2', 'clickData'), State('hexgrid-1-container', 'children'), State('hexgrid-2-container', 'children') ) def swap_graphs(clickData, hexgrid_1_children, hexgrid_2_children): clicked_graph_id = 1 # hexgrid-2 がクリックされたと仮定すると、ユースケースに基づいてこのロジックを変更できます clicked_graph_id == 1 の場合: # hexgrid-1 と hexgrid-2 の間でグラフを交換します hexgrid_2_children、hexgrid_1_children を返す hexgrid_1_children、hexgrid_2_childrenを返す