Edit: I solved this by adding category_orders={'Team' : list(dff['Team'])}
as an argument to px.bar()
. This worked because dff was already sorted in the way I wanted it to appear, so I could explicitly define the order using category_orders
Original question:
I am developing a web app that plots college basketball data scraped from KenPom.com (can be seen at kenpomgraphs.pythonanywhere.com). The first figure is a bar chart using px.bar(), and it is working as intended for the most part. However, when I select conferences that include both positive and negative values for Y, the figure leaves a huge gap between the positive and negative bars.
If I copy the exact same code into a jupyter notebook (replacing return [fig1]
with fig1.show()
) I get the desired output.
Here is the code that produces the graph along with the callbacks that provide the arguments. df
is a dataframe that contains all the data. I filter it down to dff
based on the arguments provided to the function. I tried adding things like .reset_index()
and .copy()
thinking maybe it was a problem with the index or somehow referencing the unfiltered dataframe, but that has not changed the output.
@app.callback(
[Output('fig1', 'figure')],
[Input('stat-column', 'value'),
Input('number-teams', 'value'),
Input('conf', 'value')]
)
def update_figure_1(stat_column_name, number_teams, conf):
if stat_column_name == 'AdjD' or stat_column_name == 'OppD':
dff = df.loc[df['Conf'].isin(conf)].sort_values(by=stat_column_name, ascending=True).head(number_teams).reset_index().copy()
else: dff = df.loc[df['Conf'].isin(conf)].sort_values(by=stat_column_name, ascending=False).head(number_teams).reset_index().copy()
fig1 = px.bar(data_frame=dff,
x='Team',
y=stat_column_name,
color='Conf',
color_discrete_map=COLORS
)
fig1.update_traces(hovertemplate='%{x}: %{y}')
fig1.update_traces(marker=dict(line=dict(
width=2,
color='DarkSlateGrey')))
fig1.update_yaxes(range=[min(dff[stat_column_name]) - abs((min(dff[stat_column_name])*.2)), max(dff[stat_column_name])*1.15])
if stat_column_name == 'AdjD' or stat_column_name == 'OppD' or stat_column_name == 'Rk':
fig1.update_layout(xaxis_categoryorder = 'total ascending')
else: fig1.update_layout(xaxis_categoryorder = 'total descending')
fig1.update_layout(transition_duration=500)
fig1.update_yaxes(title=stat_column_name)
fig1.update_xaxes(title='')
return [fig1]
I am deploying the app using pythonanywhere. When I execute the code in a bash console I can confirm that dff
only contains the rows I wish to display, so I canβt understand why this gap is appearing, and why the same code does not produce the gap when run in a jupyter notebook.
Edit: I solved this by adding category_orders={'Team' : list(dff['Team'])}
as an argument to px.bar()