Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
505 views
in Technique[技术] by (71.8m points)

python - Plotly: How to remove empty dates from x axis?

I have a Dataframe

   Date        Category    Sum
0  2019-06-03    "25M"      34
1  2019-06-03    "25M"      60
2  2019-06-03    "50M"      23
3  2019-06-04    "25M"      67
4  2019-06-05    "50M"     -90
5  2019-06-05    "50M"     100
6  2019-06-06    "100M"     6
7  2019-06-07    "25M"     -100
8  2019-06-08    "100M"     67
9  2019-06-09    "25M"      450
10 2019-06-10    "50M"      600
11 2019-06-11    "25M"      -9
12 2019-07-12    "50M"      45
13 2019-07-13    "50M"      67
14 2019-07-14    "100M"    130
15 2019-07-14    "50M"      45
16 2019-07-15    "100M"    100
17 2019-07-16    "25M"     -90
18 2019-07-17    "25M"     700
19 2019-07-18    "25M"     -9

I want to create a plotly graph showing the addition of "Sum" for different "Category" on Every described date, but want to remove dates, if they don't have any data.

Code

df["Date"]=pd.to_datetime(df["Date"], format=("%Y%m%d"))
df=df.sort_values(["Date","Category","Sum"],ascending=False)
df=round(df.groupby(["Date","Category"]).agg({"Sum":"sum"}).reset_index(),1)


fig = px.bar(df, x=df["Date"] , y='Sum',barmode="group",color="Category") 
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()

enter image description here

I am getting graph like this but I want to remove the empty Dates from the plotly graph

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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:

enter image description here

And here, as you already know, is the same visualization without rangebreaks=[dict(values=dt_breaks)]:

enter image description here

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()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...