Plotly如何通过多下拉菜单过滤DataFrame并绘制多分组柱状图
问题说明
- 参考Stack Overflow相关问题进行开发,使用数据集为Tableau公开的Sample Superstore销售数据集
- 我是Plotly新手,当前需求为在原问题基础上新增过滤条件:通过年份和商品类别两个维度过滤数据,绘制各区域每季度的总销售额柱状图
- 目前已成功复现原问题中的折线图效果,但无法实现预期的柱状图效果。需求要求一年4个季度、共4个区域,因此任意过滤状态下需至少展示16根柱子
当前实现代码
import plotly.graph_objs as go import pandas as pd import numpy as np file = pd.read_excel(r"Sample - Superstore.xlsx") sales = file[['Sales','Region', 'Order Date','Category', 'State']] sales["Quarters"] = sales['Order Date'].apply(lambda x: x.quarter) sales["Years"] = sales['Order Date'].apply(lambda x: x.year) df = sales.groupby(['Years','Quarters', 'Region', 'Category'], as_index = False).sum() df_input = df.copy() years = df['Years'].unique().tolist() categories = df['Category'].unique().tolist() regions = df['Region'].unique().tolist() quarters = df['Quarters'].unique().tolist() dfs = {} for year in years: dfs[year]=pd.pivot_table(df[df['Years']==year], values='Sales', index=['Quarters','Region'], columns=['Category'], aggfunc=np.sum) # find row and column unions common_cols = [] common_rows = [] for df in dfs.keys(): common_cols = sorted(list(set().union(common_cols,list(dfs[df])))) common_rows = sorted(list(set().union(common_rows,list(dfs[df].index)))) df_common = pd.DataFrame(np.nan, index=common_rows, columns=common_cols) # reshape each dfs[df] into common dimensions dfc={} for df_item in dfs: #print(dfs[unshaped]) df1 = dfs[df_item].copy() s=df_common.combine_first(df1) df_reshaped = df1.reindex_like(s) dfc[df_item]=df_reshaped # plotly start fig = go.Figure() # for year in all_years: # df2 = group_sales.loc[group_sales["Years"] == year] # all_quarters =list(sorted(set(df2["Quarters"].astype(str)))) # all_regions =list(sorted(set(df2["Region"].astype(str)))) # fig.add_trace(go.Bar(x= all_quarters, y=df2.loc[df2["Region"] == all_regions[0]]["Sales"], name=all_regions[0],marker_color='blue', visible=(year== default_year))) # fig.add_trace(go.Bar(x= all_quarters, y= df2.loc[df2["Region"] == all_regions[1]]["Sales"], name=all_regions[1], marker_color='lightblue', visible=( year == default_year))) # fig.add_trace(go.Bar(x= all_quarters, y= df2.loc[df2["Region"] == all_regions[2]]["Sales"],name= all_regions[2],marker_color='grey', visible=(year== default_year))) # fig.add_trace(go.Bar(x= all_quarters, y= df2.loc[df2["Region"] == all_regions[3]]["Sales"],name=all_regions[3], marker_color='red', visible=(year== default_year))) # year_plot_names.extend([year]*4) print(common_cols) for col in common_cols: # fig.add_trace(go.Bar(x= all_quarters, y=df2.loc[df2["Region"] == all_regions[0]]["Sales"], name=all_regions[0],marker_color='blue', visible=(year== default_year))) fig.add_trace(go.Bar(x= quarters, name= regions[0],marker_color='blue', visible= True)) fig.add_trace(go.Bar(x= quarters, name= regions[1],marker_color='lightblue', visible= True)) fig.add_trace(go.Bar(x= quarters, name= regions[2],marker_color='grey', visible= True)) fig.add_trace(go.Bar(x= quarters, name= regions[3],marker_color='red', visible= True)) # fig.add_trace(go.Bar(x= regions,marker_color='blue', visible= True)) # fig.add_trace(go.Scatter(x=regions, # visible=True, # marker=dict(size=12, line=dict(width=2)), # marker_symbol = 'diamond',name=col # ) # ) fig.show() # menu setup updatemenu= [] # buttons for menu 1, names buttons=[] # create traces for each color: # build argVals for buttons and create buttons for df in dfc.keys(): argList = [] for col in dfc[df]: temp = [] j = 0 # for i in range(0,4): # temp2 = [] # for i in range(0,4): # temp2.append(dfc[df][col].values[j]) # j+=1 # temp.append(temp2) # argList.append(temp) print(dfc[df][col]) argList.append(dfc[df][col].values) argVals = [ {'y':argList}] buttons.append(dict(method='update', label=df, visible=True, args=argVals)) print(buttons) # buttons for menu 2, colors b2_labels = common_cols # matrix to feed all visible arguments for all traces # so that they can be shown or hidden by choice b2_show = [list(b) for b in [e==1 for e in np.eye(len(b2_labels))]] buttons2=[] buttons2.append({'method': 'update', 'label': 'All', 'args': [{'visible': [True]*len(common_cols)}]}) # create buttons to show or hide for i in range(0, len(b2_labels)): buttons2.append(dict(method='update', label=b2_labels[i], args=[{'visible':b2_show[i]}] ) ) # add option for button two to hide all buttons2.append(dict(method='update', label='None', args=[{'visible':[False]*len(common_cols)}] ) ) # some adjustments to the updatemenus updatemenu=[] your_menu=dict() updatemenu.append(your_menu) your_menu2=dict() updatemenu.append(your_menu2) updatemenu[1] updatemenu[0]['buttons']=buttons updatemenu[0]['direction']='down' updatemenu[0]['showactive']=True updatemenu[1]['buttons']=buttons2 updatemenu[1]['y']=0.6 fig.update_layout(showlegend=False, updatemenus=updatemenu) fig.update_layout(yaxis=dict(range=[0,df_input['Sales'].max()+0.4])) # title fig.update_layout( title=dict( text= "<i>Filtering with multiple dropdown buttons</i>", font={'size':18}, y=0.9, x=0.5, xanchor= 'center', yanchor= 'top')) # button annotations fig.update_layout( annotations=[ dict(text="<i>Year</i>", x=-0.4, xref="paper", y=1.1, yref="paper", align="left", showarrow=False, font = dict(size=16, color = 'steelblue')), dict(text="<i>Category</i>", x=-0.4, xref="paper", y=0.7, yref="paper", align="left", showarrow=False, font = dict(size=16, color = 'steelblue') ) ]) fig.show()
内容的提问来源于stack exchange,提问作者Andrew Tjen
相关产品推荐
相关产品推荐

