How to highlight a plotline chart with vertical color bar for specific weekdays (saturday and sunday)? [duplicate]

冷暖自知 提交于 2021-02-11 06:52:11

问题


i plotted a daily line plot for flights and i would like to highlight all the saturdays and sundays. I'm trying to do it with axvspan but i'm struggling with the use of it? Any suggestions on how can this be coded?

(flights.loc[flights['date'].dt.month.between(1, 2), 'date']
         .dt.to_period('D')
         .value_counts()
         .sort_index()
         .plot(kind="line",figsize=(12,6))
 )

Thx in advance for any help provided


回答1:


Using a date column of type pandas timestamp, you can get the weekday of a date directly using pandas.Timestamp.weekday. Then you can use df.iterrows() to check whether or not each date is a saturday or sunday and include a shape in the figure like this:

for index, row in df.iterrows():
    if row['date'].weekday() == 5 or row['date'].weekday() == 6:
        fig.add_shape(...)

With a setup like this, you would get a line indicating whether or not each date is a saturday or sunday. But given that you're dealing with a continuous time series, it would probably make sense to illustrate these periods as an area for the whole period instead of highlighting each individual day. So just identify each saturday and set the whole period to each saturday plus pd.DateOffset(1) to get this:

Complete code with sample data

# imports
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
import datetime

pd.set_option('display.max_rows', None)

# data sample
cols = ['signal']
nperiods = 20
np.random.seed(12)
df = pd.DataFrame(np.random.randint(-2, 2, size=(nperiods, len(cols))),
                  columns=cols)
datelist = pd.date_range(datetime.datetime(2020, 1, 1).strftime('%Y-%m-%d'),periods=nperiods).tolist()
df['date'] = datelist 
df = df.set_index(['date'])
df.index = pd.to_datetime(df.index)
df.iloc[0] = 0
df = df.cumsum().reset_index()
df['signal'] = df['signal'] + 100

# plotly setup
fig = px.line(df, x='date', y=df.columns[1:])
fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,255,0.1)')
fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,255,0.1)')

for index, row in df.iterrows():
    if row['date'].weekday() == 5: #or row['date'].weekday() == 6:
        fig.add_shape(type="rect",
                        xref="x",
                        yref="paper",
                        x0=row['date'],
                        y0=0,
#                         x1=row['date'],
                        x1=row['date'] + pd.DateOffset(1),
                        y1=1,
                        line=dict(color="rgba(0,0,0,0)",width=3,),
                        fillcolor="rgba(0,0,0,0.1)",
                        layer='below') 
fig.show()



回答2:


You can use pandas' dt.weekday to get an integer corresponding to the weekday of a given date. 5 equals to Saturday and 6 to Sunday (Monday is 0). You can use this information as an additional way to slice your dataframe and filter those entries that belong to either Saturdays or Sundays. As you mentioned they can be highlighted with axvspan and matplotlib versions >3 are able to use the datetime objects as an input. 1 day has to be added via datetime.timedelta, because no rectangle will be drawn if xmin=xmax. Here is the code

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import datetime

#create sample data and dataframe
datelist = pd.date_range(start="2014-12-09",end="2015-03-02").tolist()
datelist += datelist #test to see whether it works with multiple entries having the same date
flights = pd.DataFrame(datelist, columns=["date"])

#plot command, save object in variable
plot = flights.loc[flights['date'].dt.month.between(1, 2), 'date'].dt.to_period('D').value_counts().sort_index().plot(kind="line",figsize=(12,6))

#filter out saturdays and sundays from the date range needed
weekends = flights.loc[(flights['date'].dt.month.between(1, 2)) & ((flights['date'].dt.weekday == 5) | (flights['date'].dt.weekday == 6)), 'date']
#5 = Saturday, 6 = Sunday

#plot axvspan for every sat or sun, set() to get unique dates
for day in set(weekends.tolist()):
    plot.axvspan(day, day + datetime.timedelta(days=1))


来源:https://stackoverflow.com/questions/65170902/how-to-highlight-a-plotline-chart-with-vertical-color-bar-for-specific-weekdays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!