我在做以下事情時遇到了很大的困難。我有一個由 css 格式化的破折號應用程序,以顯示在不同的容器中。標記為“hexgrid-1-container”的容器是最大的容器,而其他容器較小,並圍繞該容器組織。我想更新我的破折號應用程序,以便每當單擊另一個容器中的圖形/圖形時,它都會出現在“hexgrid-1-container”中,而之前位於“hexgrid-1-container”中的圖形會出現在較小的容器中容器。
我有一個破折號應用程序,如下所示:
導入破折號 將 dash_core_components 導入為 dcc 將 dash_html_components 導入為 html 從 dash.dependencies 導入輸入、輸出、狀態 從 jupyter_dash 導入 JupyterDash 將plotly.express導入為px 導入plotly.graph_objects作為go 將 pandas 導入為 pd 導入sqlite3 導入語言環境 將 numpy 導入為 np 將plotly.figure_factory匯入為ff 將plotly.express導入為px # 設定格式化的區域設置 locale.setlocale(locale.LC_ALL, '') 應用程式 = dash.Dash(__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={"height": "100%", "width": "100%"}) ]), html.Div(className='us-map-container', style={'border': '1px 純黑'}, Children=[ dcc.Graph(id='us-map-graph', style={"height": "100%", "width": "100%"}) ]), html.Div(className='第五容器', style={'border': '1px 純黑'}, Children=[ # dcc.Graph(id='us-map-graph', style={"height": "100%", "width": "100%"}) #html.H2("第五個容器") ]), html.Div(className='第六個容器', style={'border': '1px 純黑'}, Children=[ # dcc.Graph(id='us-map-graph', style={"height": "100%", "width": "100%"}) #html.H2("第6個容器") ]) ]) @app.callback( 輸出('hexgrid-1','數字'), 輸入('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) # 過濾掉相關列,如果想要所有列可以跳過這一步驟。 related_columns = data[data['name'].isin(['TranType', 'MessageTypeIdentifier', 'MerchantType', 'IResponseCode'])] # 使用列名建立十六進位網格 plot_data = go.Scatter(x=relevant_columns.index, y=relevant_columns['name'], text=relevant_columns['name'], 標記=dict(符號='六邊形',大小=30),模式='標記文字') 版面 = go.Layout(title="選擇類別") 返回 go.Figure(data=[plot_data],layout=layout) @app.callback( 輸出('hexgrid-2','圖'), 輸出('hexgrid-2','樣式'), 輸入('hexgrid-1','clickData') ) def render_hexgrid_2(clickData): # 開啟一個新的資料庫連接 conn = sqlite3.connect(r"C:\Users\HituJani\Downloads\txns.db") 如果 clickData 為 None: 返回 go.Figure(), {"display": "none"}別的: 類別 = clickData['點'][0]['文字'] # 取得交易表中的所有欄位 查詢=''' PRAGMA table_info(交易) ''' # 取得數據 資料 = pd.read_sql_query(查詢, conn) # 過濾掉相關數值特徵列 related_columns = data[data['name'].isin(['TransactionAmount', 'OutstandingAmount', 'CurrentBalance', '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(theta) * np.sin(phi) y = np.sin(theta) * np.sin(phi) z = np.cos(phi) # 使用球體標記建立 3D 散佈圖 分散 = go.Scatter3d( x=x, y=y, z=z, mode='標記文字', 標記=字典( 大小=12, 顏色=np.arange(len(relevant_columns)), colorscale='Viridis', 符號='圓圈', 不透明度=0.8 ), 文本=relevant_columns['名稱'], 懸停訊息='文字' ) # 使用網格建立線框球體 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)) 球體 = go.Mesh3d(x=x_sphere.ravel(), y=y_sphere.ravel(), z=z_sphere.ravel(), 不透明度=0.1, 顏色='青色') # 將散佈圖和線框圖合併為一個圖形 Fig = go.Figure(data=[散點圖, 球體]) 圖.update_layout( 邊距=dict(l=0, r=0, b=0, t=0), 場景=字典( xaxis=dict(標題=無,可見=假), yaxis=dict(標題=無,可見=假), zaxis=dict(標題=無,可見=假), ), 模板='plotly_dark' ) 返回無花果,{“高度”:“50vh”,“寬度”:“100%”,“顯示”:“內聯塊”} # 定義將更新繪圖、反白球體並啟用向下鑽取的回呼函數 @app.callback( 輸出('基本圖','圖'), 輸入('hexgrid-2','clickData'), 狀態('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]['文字'] numeric_feature = clickData_hexgrid_2['點'][0]['文字'] # SQL 查詢根據選定的類別和數值特徵檢索聚合數據 查詢 = f''' SELECT {category}, WeekOfMonth, SUM({numerical_feature}) AS 總計金額 來自交易 按{類別}分組, 每月一周 以總金額 DESC 排序 ''' # 從資料庫取得數據 df_base = pd.read_sql(查詢, conn) # 關閉資料庫連接 conn.close() # 設定總計列的格式 df_base['TotalAmount'] = df_base['TotalAmount'].apply(lambda x: locale.currency(x, grouping=True)) # 使用球體標記建立 3D 散佈圖 圖 = go.Figure() # 定義 WeekOfMonth 值的色階 色階 = [ [0, '藍色'], # 第 1 週:藍色 [0.25, '紫色'], # 第 2 週:紫色 [0.5, 'darkorange'], # 第 3 週:深橙色 [0.75, '黃色'], # 第 4 週:黃色 [1, '粉紅色'] # 第 5 週:粉紅色 ] # 新增散點圖軌跡 圖.add_trace( 去.Scatter3d( x=df_base[類別], y=df_base['WeekOfMonth'].astype(int), z=df_base['總金額'], mode='標記文字', 標記=字典( size=5, # 調整標記的大小,使其變小 symbol='circle', # 使用 'circle' 符號表示球體 顏色=df_base['WeekOfMonth'], 色標=色標, ), textposition='頂部中心', 懸停模板=( f"<b>{類別}</b>: %{{x}}<br>" “<b>總金額</b>:%{z}<br>” “<b>每月週</b>:%{y}<br>” ) ) ) # 動態設定y軸範圍 y_max = df_base['WeekOfMonth'].max() 圖.update_layout( 場景=字典( x軸=字典( 標題=類別, title_font = dict(大小= 14,顏色='暗橙色'), visible=False # 隱藏x軸 ), y軸=字典( title='一個月中的第幾週', title_font = dict(大小= 14,顏色='紫色'), 勾選模式='數組', 刻度值=[0.5, 1.5, 2.5, 3.5, 4.5, 5.5], ticktext=['1', '2', '3', '4', '5'], # 將刻度標籤顯示為 1, 2, 3, 4, 5], visible=False # 隱藏 y 軸 ), z軸=字典( title=f'總計{numerical_feature} ($)', title_font = dict(大小= 14,顏色='黃色'), 自動範圍='反轉', visible=False # 隱藏 z 軸 ), ), x軸=字典( 型態='類別', 刻度模式='線性', 刻度角=45, 自動保證金=真, visible=False # 隱藏x軸標籤 ), margin=dict(l=10, r=10, t=10, b=10), # 增加b值以放大檢視窗口 模板='plotly_dark', ) 返回無花果 除了異常 e: 列印(f“錯誤:{e}”) 返回 go.Figure() @app.callback( 輸出('美國地圖圖','圖'), 輸出('我們地圖圖','風格'), 輸入('基本圖','clickData'), 狀態('hexgrid-1','clickData'), 狀態('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: # 傳回一個空圖形並隱藏地圖 返回 go.Figure(), {"display": "none"} # 從hexgrid-1中取得選定的類別,從hexgrid-2中取得數值特徵 selected_category = hexgrid_1_clickData['點'][0]['文字'] numeric_feature = hexgrid_2_clickData['點'][0]['文字'] # 從base_plot_click_data取得選定的子類別 選定的子類別=無 如果 base_plot_click_data 不是 None: selected_subcategory = base_plot_click_data['點'][0]['x'] # 開啟一個新的資料庫連接 conn = sqlite3.connect(r"C:\Users\HituJani\Downloads\txns.db") # SQL 查詢會依狀態擷取所選類別、子類別和數字特徵的交易數據 查詢 = f''' SELECT StateCode, {selected_category}, SUM({numerical_feature}) AS TotalTransactionAmount 來自交易 哪裡 {selected_category} = ? 按州代碼分組,{selected_category} ''' # 執行查詢並將結果擷取到DataFrame中 state_data = pd.read_sql(query, conn, params=(selected_subcategory,)) # 關閉資料庫連接 conn.close() # 使用過濾後的資料建立 Choropleth 地圖 無花果 = px.choropleth( 數據幀=狀態數據, locationmode='美國各州', 位置='州代碼', 範圍='美國', color='總交易金額', hide_data={'StateCode': True, 'TotalTransactionAmount': ':$,f'}, color_continuous_scale='紅色', labels={'TotalTransactionAmount': '交易總金額'}, 模板='plotly_dark' ) 圖.update_traces( hidetemplate="<b>%{customdata[0]}</b><br>" "<b>總交易金額</b>: $%{customdata[1]:,.2f}<br>", customdata=list(zip(state_data['StateCode'], state_data['TotalTransactionAmount'])) ) 圖.update_layout( title_text=f'類別:{selected_category}、子類別:{selected_subcategory}的州總交易金額', title_xanchor='中心', title_font=dict(大小=12), 標題_x=0.5, 地理=字典(範圍='美國'), ) # 返回圖形並設定顯示樣式為block(可見) 返回無花果,{“顯示”:“塊”} 除了異常 e: 列印(f“錯誤:{e}”) 返回 go.Figure(), {"display": "none"} 如果 __name__ == '__main__': app.run_server(debug=True, use_reloader=False)
另外,我還有這個整理網頁的css檔:
/* styles.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; 內邊距:2 像素 2 像素 2 像素 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 背景:hsla(0, 7%, 11%, 0.9); 位置:相對; } .hexgrid-2-container { 網格面積:1/3/2/4; 填充:3rem 4rem 4rem; 寬度: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 背景:hsl(0, 7%, 11%, 0.9); 位置:相對; } .base-plot-container { /* 在此新增基本圖容器的自訂樣式 */ 網格面積:2/3/3/4; 填充:3rem 4rem 4rem; 寬度: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 背景:hsl(0, 7%, 11%, 0.9); 位置:相對; } .us-map-container { 網格面積:3/3/4/4; 填充:3rem 4rem 4rem; 寬度: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 背景:hsl(0, 7%, 11%, 0.9); 位置:相對; } .第五容器{ 網格面積: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 背景:hsl(0, 7%, 11%, 0.9); 位置:相對; } .第六個容器{ 網格面積: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 背景:hsl(0, 7%, 11%, 0.9); 位置:相對; }
我嘗試更新回調函數,但進展不大,而且似乎我做錯了很多事情。實現此功能的最直接方法是什麼?先謝謝您。
您可以進行回呼來偵聽點擊事件,交換圖形位置,然後將圖形回到更新的位置。您需要根據您的用例設定點擊邏輯。你可以實現這樣的東西:
#