I have a df like this:
level_0 DATE ONI positive YEAR
686 sst 1960-03-15 -0.364453 False 1960
687 sst 1960-04-15 -0.366851 False 1960
688 sst 1960-05-15 -0.321550 False 1960
689 sst 1960-06-15 -0.382227 False 1960
690 sst 1960-07-15 -0.374074 False 1960
... ... ... ... ...
1363 sst 2016-08-15 -0.597598 False 2016
1364 sst 2016-09-15 -0.784883 False 2016
1365 sst 2016-10-15 -0.900240 False 2016
1366 sst 2016-11-15 -1.006226 False 2016
1367 sst 2016-12-15 -1.065392 False 2016
[682 rows x 5 columns]
I want to plot my data with xaxis every nth year so i did this code:
fig = plt.figure('ONI', figsize=(15,20), dpi=200)
ax = fig.add_axes([0.15,0.15,0.7,0.7])
df_oni.plot(x='DATE',y="ONI",kind='bar', alpha=0.5, color=df_oni.positive.map({True: 'r', False: 'b'}),ax=ax)
date_form = DateFormatter("%Y")
ax.xaxis.set_major_formatter(date_form)
ax.xaxis.set_major_locator(mdates.YearLocator(base=5))
ax.xaxis.set_tick_params(rotation=0)
ax.set_title("Indice ONI",fontsize= 14,fontweight="bold")
# Define the date format
ax.set_ylabel("Valor del Índice\n", fontsize = 10.0)
ax.yaxis.set_major_locator(MaxNLocator(integer=True, min_n_ticks=1))
ax.set_xlabel("")
I don't understand why even with ax.xaxis.set_major_locator(mdates.YearLocator(base=5))
i get this figure with only 1 year in the xaxis:
Would you mind to help me? Thanks in advance.
CodePudding user response:
This is related to the way pandas
produces the bar
plot where it just indexes the x-position (to verify: ax.get_xlim()
gives (-0.5, 681.5)
).
The easiest workaround is to use matplotlib directly:
ax.bar(df_oni.DATE,df_oni.ONI, width=20, alpha=0.5, color=df_oni.positive.map({True: 'r', False: 'b'}))
(you'll need to increase the bar width to say 20 for better visual impression)
Example:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
fig = plt.figure('ONI', figsize=(15,20), dpi=200)
ax = fig.add_axes([0.15,0.15,0.7,0.7])
df_oni = pd.DataFrame({'DATE': pd.date_range('1960-03', periods=682, freq='M'),
'ONI': (np.random.rand(682) - .5)*5})
df_oni['positive'] = df_oni.ONI>0
ax.bar(df_oni.DATE,df_oni.ONI, width=20, alpha=0.5, color=df_oni.positive.map({True: 'r', False: 'b'}))
ax.xaxis.set_major_locator(mdates.YearLocator(base=5))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y"))
ax.xaxis.set_tick_params(rotation=0)
ax.yaxis.set_major_locator(mticker.MaxNLocator(integer=True, min_n_ticks=1))
ax.set_title("Indice ONI",fontsize= 14,fontweight="bold")
ax.set_ylabel("Valor del Índice\n", fontsize = 10.0)
ax.set_xlabel("")