This problem comes from the fact that plotly interprets your 'Date'
as dates and creates a continuous period between the oldest and newest timestamp, effectively showing dates with no associated data as gaps. One solution is to take the first and last date in your date column, and make a complete list of dates in that period, and then sort out which dates do not have any observations, and store that in a variable named dt_breaks
. Then, at last, you can include those dates in:
fig.update_xaxes(
rangebreaks=[dict(values=dt_breaks)] # hide dates with no values
)
This will drop those dates in your visualization, and keep the x-values formatted as dates so that you can subset the data using your buttons:
And here, as you already know, is the same visualization without rangebreaks=[dict(values=dt_breaks)]
:
To make this work as simply as possible, I rearranged the date column using df=df.sort_values(["Date","Category","Sum"],ascending=True)
instead of df=df.sort_values(["Date","Category","Sum"],ascending=False)
as in your original code snippet
Complete code:
import pandas as pd
import plotly.express as px
df = pd.DataFrame({'Date': {0: '2019-06-03',
1: '2019-06-03',
2: '2019-06-03',
3: '2019-06-04',
4: '2019-06-05',
5: '2019-06-05',
6: '2019-06-06',
7: '2019-06-07',
8: '2019-06-08',
9: '2019-06-09',
10: '2019-06-10',
11: '2019-06-11',
12: '2019-07-12',
13: '2019-07-13',
14: '2019-07-14',
15: '2019-07-14',
16: '2019-07-15',
17: '2019-07-16',
18: '2019-07-17',
19: '2019-07-18'},
'Category': {0: '"25M"',
1: '"25M"',
2: '"50M"',
3: '"25M"',
4: '"50M"',
5: '"50M"',
6: '"100M"',
7: '"25M"',
8: '"100M"',
9: '"25M"',
10: '"50M"',
11: '"25M"',
12: '"50M"',
13: '"50M"',
14: '"100M"',
15: '"50M"',
16: '"100M"',
17: '"25M"',
18: '"25M"',
19: '"25M"'},
'Sum': {0: 34,
1: 60,
2: 23,
3: 67,
4: -90,
5: 100,
6: 6,
7: -100,
8: 67,
9: 450,
10: 600,
11: -9,
12: 45,
13: 67,
14: 130,
15: 45,
16: 100,
17: -90,
18: 700,
19: -9}})
df["Date"]=pd.to_datetime(df["Date"], format=("%Y-%m-%d"))
df=df.sort_values(["Date","Category","Sum"],ascending=True)
df=round(df.groupby(["Date","Category"]).agg({"Sum":"sum"}).reset_index(),1)
dt_all = pd.date_range(start=df['Date'].iloc[0],end=df['Date'].iloc[-1])
dt_obs = [d.strftime("%Y-%m-%d") for d in df['Date']]
dt_breaks = [d for d in dt_all.strftime("%Y-%m-%d").tolist() if not d in dt_obs]
df=df.set_index('Date')
#fig = px.bar(df, x=df.index.strftime("%Y/%m/%d") , y='Sum',barmode="group",color="Category")
fig = px.bar(df, x=df.index , y='Sum',barmode="group",color="Category")
fig.update_xaxes(
rangebreaks=[dict(values=dt_breaks)] # hide dates with no values
)
fig.update_xaxes(
rangeslider_visible=True,
rangeselector=dict(
buttons=list([
dict(count=1, label="day", step="day", stepmode="todate"),
dict(count=24, label="montly", step="month", stepmode="todate"),
dict(count=1, label="year", step="year", stepmode="todate"),
dict(step="all")
])
))
fig.show()