Matplotlib df.dataframe x axis showing month and day - pandas

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)

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?

How to format in Matplotlib the x axis ticks to the only hours and minutes and define regular intervals?

I would like to have in the x axis the following ticks numbers and intervals:
[6:00; 8:00; 10:00: 12:00; 14:00, 16:00, 18:00]. The point at '12:00' should also be in the center of the figure, now it is shifted to the right
I tried to convert the column 'time' to a datetime format, but I get an error:
TypeError: <class 'datetime.time'> is not convertible to datetime
My code looks like this:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df3 = pd.read_excel(r'results.xlsx')
# failed attempt
df3["time"] = pd.to_datetime(df3["time"]).dt.date
# plotting
color = 'black'
ax1 = sns.lineplot(x = 'time', y = 'parabolic', data = df3, color = color,
label='Light intensity')
ax2 = ax1.twinx()
ax2 = sns.scatterplot(x = 'time', y = 'Gas-exchange_p', hue= 'Sampling',
marker='v', s=200, data = df3, label= 'Measurement time points')
plt.legend()
plt.show()
My dataframe in excel looks like this:
time y
12:00:00 AM 0
12:01:00 AM 0
12:02:00 AM 0
...
2:00:40 PM 416
...

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:

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

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!

ax.twinx label appears twice

I have been trying to make a chart based on an excel, using Matplotlib and Seaborn. Code is from the internet, adapted to what I want.
The issue is that the legend appears 2 times.
Do you have any recommendations?
Report screenshot: enter image description here
Excel table is:
Month Value (tsd eur) Total MAE
0 Mar 2020 14.0 1714.0
1 Apr 2020 22.5 1736.5
2 Jun 2020 198.0 1934.5
3 Jan 2021 45.0 1979.5
4 Feb 2021 60.0 2039.5
5 Jan 2022 67.0 2106.5
6 Feb 2022 230.0 2336.5
7 Mar 2022 500.0 2836.5
Code is:
import pandas as pd
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
mae=pd.read_excel('Book1.xlsx')
mae['Month'] = mae['Month'].apply(lambda x: pd.Timestamp(x).strftime('%b %Y'))
a=mae['Value (tsd eur)']
b=mae['Total MAE']
#Create combo chart
fig, ax1 = plt.subplots(figsize=(20,12))
color = 'tab:green'
#bar plot creation
ax1.set_title('MAE Investments', fontsize=25)
ax1.set_xlabel('Month', fontsize=23)
ax1.set_ylabel('Investments (tsd. eur)', fontsize=23)
ax1 = sns.barplot(x='Month', y='Value (tsd eur)', data = mae, palette='Blues',label="Value (tsd eur)")
ax1.tick_params(axis='y',labelsize=20)
ax1.tick_params(axis='x', which='major', labelsize=20, labelrotation=40)
#specify we want to share the same x-axis
ax2 = ax1.twinx()
color = 'tab:red'
#line plot creation
ax2.set_ylabel('Total MAE Value', fontsize=16)
ax2 = sns.lineplot(x='Month', y='Total MAE', data = mae, sort=False, color='blue',label="Total MAE")
ax2.tick_params(axis='y', color=color,labelsize=20)
h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax1.legend(h1+h2, l1+l2, loc=2, prop={'size': 24})
for i,j in b.items():
ax2.annotate(str(j), xy=(i, j+30))
for i,j in a.items():
ax1.annotate(str(j), xy=(i, j+2))
#show plot
print(mae)
plt.show()
Update: found the answer here:
Secondary axis with twinx(): how to add to legend?
code used:
lines, labels =ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, title="Legend", loc=2, prop={'size': 24})
insteaf of:
for i,j in b.items():
ax2.annotate(str(j), xy=(i, j+30))
for i,j in a.items():
ax1.annotate(str(j), xy=(i, j+2))