Matplotlib Plot Every Other Month w/Ticks and Grid lines Each Month - matplotlib

I have code that looks like this below and I'm trying to plot every other month on the x axis starting with "Jan" with xticks/grid lines vertical at every or each month and year shown. However, i've tried two solutions and nothing happens and i get no error. In other words, it seems like the options I've tried don't have any effect on the plot. Here is the code for the plot portion and you can see I've tried "MonthLocator" and "mdates".
#PRODUCE AND VISUALIZE FORECAST
pred_uc = results.get_forecast(steps=6)
pred_ci = pred_uc.conf_int()
import matplotlib.dates as mdates
#from matplotlib.dates import MonthLocator
ax = y['2019':].plot(label='observed', figsize=(14, 7))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
#ax.xaxis.set_major_locator(MonthLocator(interval=2))
pred_uc.predicted_mean.plot(ax=ax, label='Forecast')
ax.fill_between(pred_ci.index,
pred_ci.iloc[:, 0],
pred_ci.iloc[:, 1], color='k', alpha=.25)
ax.set_xlabel('Date')
ax.set_ylabel('MOS Wind Speed')
#add the LT monthly average to plot
from datetime import date
cm = date.today().month
lty = y.groupby(y.index.month).mean()
lty = lty.to_frame()
lty.columns=['LT Mean']
ltyc = lty.iloc[cm-1:12].reset_index() # extract curr month to end of LT mean monthly wind speed
#create date sequence using date format of df = y
ltyc['Date'] = pd.to_datetime(ltyc["Date"], format='%m').apply(lambda dt: dt.replace(year=2020))#convert the "Date" col to yyyy-mm-dd
ltycs = pd.Series(ltyc['LT Mean'].values, index=ltyc['Date'])#convert to Series since the other plots are in series format
ltycs.plot(label='LT Mean',ax=ax,color='k')
plt.grid(b=True, which='major', color='k', linestyle='-')
plt.grid(b=True, which='minor', color='g', linestyle='-', alpha=0.2)#alpha is the minor grid thickness w/higher numbers thicker lines
plt.minorticks_on()
plt.legend()
plt.show()
Here is my plot so far below. Than you for any help with this!

Related

How correctly display AQI in a calendar plot using Python

I have a dataframe of Air Quality Index that want to display on a calendar plot but fulfilling the requirements for correct color values.
Below my code:
import pandas as pd
import calmap
import matplotlib.pyplot as plt
from matplotlib.colors import from_levels_and_colors
from matplotlib.patches import Patch
import calendar as cal
import calplot
def calendar_plot_aqi(ds, year, station):
cmap, norm = from_levels_and_colors([0,20, 40, 80, 100, 150, 200], ['#50f0e6', '#50ccaa','#f0e641','#ff5050' , '#960032', '#7D2181'])
fig, ax = plt.subplots(figsize=(20, 20))
# Shrink current axis by 20%
box = ax.get_position()
ax.set_position([box.x0*0.8, box.y0, box.width, box.height])
_ = calmap.yearplot(ds, year, ax=ax, cmap=cmap, how=None, vmin=0, vmax=220)
# _= calmap.calendarplot(ds, cmap=cmap)
legend_elements = [Patch(facecolor='#50f0e6', edgecolor='#50f0e6', label='Good'),
Patch(facecolor='#50ccaa', edgecolor='#50ccaa', label='Fair'),
Patch(facecolor='#f0e641', edgecolor='#f0e641', label='Moderate'),
Patch(facecolor='#ff5050', edgecolor='#ff5050', label='Poor'),
Patch(facecolor='#960032', edgecolor='#960032', label='Very Poor'),
Patch(facecolor='#7d2181', edgecolor='#7D2181', label='Extremely Poor')]
_ = ax.legend(handles=legend_elements, bbox_to_anchor=(0.5, -0.2), loc='upper center', ncol=6)
plt.title(f'AQI calandar plot station: {station} (year {year})')
df_AQ101 = pd.read_parquet(dir_base_aqi + f'AQ101_aqi_RF.parquet')
df_AQ101.head()
ds_AQ101=df_AQ101['aqi']
ds_AQ101.index.rename(None, inplace=True)
ds_AQ101=ds_AQ101.tz_localize(None)
calendar_plot_aqi(ds_AQ101,2021,'AQ101')
df_AQ101 is as below:
The resulting calendar plot is:
The filling colors in the calendar does not respect the colors defined for AQI as I would like. To be more clear, if, as example, the first Sunday of January 2021 the AQI is 60 I expect it will be indicated with color '#f0e641' but this is not the case (only sometimes colors are correct).
Is there a workaround to correctly display AQI values?

Matplotlib df.dataframe x axis showing month and day

The length of my x-axis is 168 (7 days * 24hrs). I want to show Jan 04th, Jan 05th ... Jan 10th) but can't seem to find how to do this.
plt.plot(t, php)
plt.title('Electricity Load of heat pump at t')
fig, axes = plt.subplots(figsize=[25,7])
fig.subplots_adjust(bottom=0.2)
tindex = np.arange(0,T)
dates = pd.date_range('20210104',periods=168, freq="H")
df = pd.DataFrame({'php1': php, 'dates': dates})
df.plot(kind='line',x='dates', y='php1',
ax=axes, color ="red", linestyle='-',
linewidth=3, grid=True)
axes.tick_params(axis='x', labelsize=15)
axes.tick_params(axis='y', labelsize=15)
axes.get_legend().remove()
axes.set_ylabel('Power[kW]', fontsize=15)
axes.set_xlabel('Timeslot[Days] ', fontsize=15)
Try this :
import matplotlib.dates as mdates
mdate = mdates.DateFormatter('%d')
ax.xaxis.set_major_formatter(mdate)

matplotlib plot from dataframe but shift dates in x labels

I have this dataframe:
dates;A;B;C
2018-01-31;1;2;5
2018-02-28;1;4;3
2018-03-31;1;5;5
2018-04-30;1;6;3
2018-05-31;1;6;7
2018-06-30;1;7;3
2018-07-31;1;9;9
2018-08-31;1;2;3
2018-09-30;1;2;10
2018-10-31;1;4;3
2018-11-30;1;7;11
2018-12-31;1;2;3
I read it:
dfr = pd.read_csv('test.dat', sep=';', header = 0, index_col=0, parse_dates=True)
and then I try to plot it:
width = 5
dfr.index = pd.to_datetime(dfr.index)
x = date2num(dfr.index)
axs.bar(x-0.5*width,dfr.iloc[:,1], width=width)
axs.bar(x+0.5*width,dfr.iloc[:,2], width=width)
axs.xaxis_date()
months = dates.MonthLocator()
axs.xaxis.set_major_formatter(dates.DateFormatter(r'\textbf{%B}'))
months_f = dates.DateFormatter('%B')
axs.xaxis.set_major_locator(months)
plt.setp( axs.xaxis.get_majorticklabels(), rotation=90)
here the modules imported:
import matplotlib.pyplot as plt
from matplotlib.dates import date2num
import datetime
import pandas as pd
import matplotlib.dates as dates
and here the result:
I do not get why x label starts with 'Feb'.
I would like to have something like 'Jan,Feb,Mar...' as x labels in the x axis.
Thanks in advance
The heights of the bar charts you made do not correspond to the labelled month, i.e. the values for Feb are actually those of Jan. Therefore, the problem is in the way you labelled the axis rather than having an incorrect plot order.
I'm not so familiar with the packages you used, so I proposed a different way of making your plot:
dfr['dates'] = pd.to_datetime(dfr['dates'])
### group by months
month_vals = dfr.groupby(dfr['dates'].map(lambda x: x.month))
month_vals = sorted(month_vals, key=lambda m: m[0])
fig, axs = plt.subplots()
spacing = 0.15
### Create the list of months and the corresponding dataframes
months, df_months = zip(*month_vals)
### In your case, each month has exactly one entry, but in case there are more, sum over all of them
axs.bar([m-spacing for m in months], [df_m.loc[:,'B'].sum() for df_m in df_months], width=0.3)
axs.bar([m+spacing for m in months], [df_m.loc[:,'C'].sum() for df_m in df_months], width=0.3)
axs.set_xticks(months)
### 1900 and 1 are dummy values; we are just initializing a datetime instance here
axs.set_xticklabels([datetime.date(1900, m, 1).strftime('%b') for m in months])
Output:

Only plotting observed dates in matplotlib, skipping range of dates

I have a simple dataframe I am plotting in matplotlib. However, the plot is showing the range of the dates, rather than just the two observed data points.
How can I only plot the two data points and not the range of the dates?
df structure:
Date Number
2018-01-01 12:00:00 1
2018-02-01 12:00:00 2
Output of the matplotlib code:
Here is what I expected (this was done using a string and not a date on the x-axis data):
df code:
import pandas as pd
df = pd.DataFrame([['2018-01-01 12:00:00', 1], ['2018-02-01 12:00:00',2]], columns=['Date', 'Number'])
df['Date'] = pd.to_datetime(df['Date'])
df.set_index(['Date'],inplace=True)
Plot code:
import matplotlib.pyplot as plt
fig, ax1 = plt.subplots(
figsize=(4,5),
dpi=72
)
width = 0.75
#starts the bar chart creation
ax1.bar(df.index, df['Number'],
width,
align='center',
color=('#666666', '#333333'),
edgecolor='#FF0000',
linewidth=2
)
ax1.set_ylim(0,3)
ax1.set_ylabel('Score')
fig.autofmt_xdate()
#Title
plt.title('Scores by group and gender')
plt.tight_layout()
plt.show()
Try adding something like:
import matplotlib.dates as mdates
myFmt = mdates.DateFormatter('%y-%m-%d')
ax1.xaxis.set_major_formatter(myFmt)
plt.xticks(df.index)
I think the dates are transformed to large integers at the time of the plot. So width = 0.75 is very small, try something bigger (like width = 20:
Matplotlib bar plots are numeric in nature. If you want a categorical bar plot instead, you may use pandas bar plots.
df.plot.bar()
You may then want to beautify the labels a bit
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame([['2018-01-01 12:00:00', 1], ['2018-02-01 12:00:00',2]], columns=['Date', 'Number'])
df['Date'] = pd.to_datetime(df['Date'])
df.set_index(['Date'],inplace=True)
ax = df.plot.bar()
ax.tick_params(axis="x", rotation=0)
ax.set_xticklabels([t.get_text().split()[0] for t in ax.get_xticklabels()])
plt.show()

Multi axes timeseries line graph using matplotlib

I am trying to create multi axis line chart where the x-axis are dates using matplotlib. As you can see in the picture below, the lines are close but all seem to be finishing on the left axis which is not correct.
Here is my code:
df.Date = pd.to_datetime(df.Date)
fig, ax = plt.subplots()
ax2= ax.twinx()
ax2.set_frame_on(True)
ax2.patch.set_visible(False)
fig.subplots_adjust(right=0.75)
years = YearLocator() # every year
months = MonthLocator() # every month
yearsFmt = DateFormatter('%Y')
ax.plot_date(df.Date,df.A, fmt="r-")
ax.plot_date(df.Date,df.B, fmt="b-")
ax2.plot_date(df.Date,df.C, fmt="y-")
ax2.plot_date(df.Date,df.D, fmt="g-")
ax.xaxis.set_major_locator(years)
ax.xaxis.set_major_formatter(yearsFmt)
ax.xaxis.set_minor_locator(months)
ax.autoscale_view()
ax2.xaxis.set_major_locator(years)
ax2.xaxis.set_major_formatter(yearsFmt)
ax2.xaxis.set_minor_locator(months)
ax2.autoscale_view()
plt.setp(ax.get_xticklabels(), fontsize=10, rotation='vertical')
plt.setp(ax2.get_xticklabels(), fontsize=10, rotation='vertical')
ax.fmt_xdata = DateFormatter('%b\n%Y')
ax2.fmt_xdata = DateFormatter('%b\n%Y')
fig.autofmt_xdate()
plt.setp(ax.get_xticklabels(), fontsize=10, rotation='vertical')
ax.set_ylabel('(%)')
ax2.set_ylabel('(%)')
ax2.set_xlabel('Date')
plt.title('Chart 1. ', fontsize=8, weight= 'bold')
plt.tight_layout()
plt.show()
need to use df1= df.sort_values(by='Date'). When i took a closer look at the data, there were a few dates out of order towards the end of the dataset that were causing the plot to revert back to 2002, causing the line to move towards the left of the graph.