Home > Software engineering >  Change month labels in matplotlib without changing the locale
Change month labels in matplotlib without changing the locale

Time:01-10

With this plot as an example: enter image description here

With the code:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.cbook as cbook

data = cbook.get_sample_data('goog.npz', np_load=True)['price_data'][0:200]

fig, ax = plt.subplots(figsize=(10, 7), constrained_layout=True)
ax.plot('date', 'adj_close', data=data)
# ax.xaxis.set_major_locator(mdates.MonthLocator())
# ax.grid(True)
ax.set_ylabel(r'Price [\$]')

ax.xaxis.set_major_formatter(
    mdates.ConciseDateFormatter(ax.xaxis.get_major_locator()))

plt.savefig("chart.png")

And I need to change the months from English to Spanish, ie: Dec to Dic, Apr to Abr, Jan to Ene and so on.

I can do it by changing the locale like so:

locale.setlocale(locale.LC_TIME, 'es_ES')

But I can't use it in the script because it runs on a serverless vm where you can't change any of the os configuration.

So I thought in changing the labels "manually" from an English month to a Spanish one. I've seen examples using DateFormatter but that doesn't work because again it relies in the system locale for the months names using strftime and any other fromatter I've seen has been using numbers not dates. So is there any solution to localize the names of the months?

CodePudding user response:

One way is to use babel.dates for the date formatting, which allows for a locale argument without changing the system locale.

The basic syntax is:

babel.dates.format_datetime([datetime object], [format], locale=[locale])

Note that the format does not use % signs. See the enter image description here

For ConciseDateFormatter this idea is the same but this class is much more complex so you will need to modify it in many places in order to get the namespaces right (similar to for example mdates.num2date in the code above instead of a plain num2dates call in the original class).

CodePudding user response:

Using this answer and the answer by Marijn I came up with this solution that uses set_xticklabels to change the labels and Babel to change the months to a localized version without changing the locale:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.cbook as cbook
import babel.dates
import matplotlib.ticker as mticker

data = cbook.get_sample_data('goog.npz', np_load=True)['price_data'][0:200]

fig, ax = plt.subplots(figsize=(10, 7), constrained_layout=True)
ax.plot('date', 'adj_close', data=data)
# ax.xaxis.set_major_locator(mdates.MonthLocator())
# ax.grid(True)
ax.set_ylabel(r'Price [\$]')

ax.xaxis.set_major_formatter(
    mdates.ConciseDateFormatter(ax.xaxis.get_major_locator()))

ticks_loc = ax.get_xticks().tolist()
ax.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
ax.set_xticklabels([babel.dates.format_datetime(mdates.num2date(x),'yyyy',locale='es') 
        if mdates.num2date(x).month == 1
        else babel.dates.format_datetime(mdates.num2date(x),'MMM',locale='es')
        for i,x in enumerate(ticks_loc)])

plt.savefig("chart.png")
  • Related