简体   繁体   中英

Matplotlib : Comma separated number format for axis

I am attempting to change the format of my axis to be comma seperated in Matplotlib running under Python 2.7 but am unable to do so.

I suspect that I need to use a FuncFormatter but I am at a bit of a loss.

Can anyone help?

Yes, you can use matplotlib.ticker.FuncFormatter to do this.

Here is the example:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as tkr

def func(x, pos):  # formatter function takes tick label and tick position
    s = str(x)
    ind = s.index('.')
    return s[:ind] + ',' + s[ind+1:]   # change dot to comma

y_format = tkr.FuncFormatter(func)  # make formatter

x = np.linspace(0,10,501)
y = np.sin(x)
ax = plt.subplot(111)
ax.plot(x,y)
ax.yaxis.set_major_formatter(y_format)  # set formatter to needed axis

plt.show()

This results in the following plot:

funcformatter 图

I know the question is old, but as I currently am searching for similar solutions, I decided to leave a comment for future reference if others need this.

For an alternative solution, use the locale module and activate locale-formatting in matplotlib.

Eg, in major parts of Europe, comma is the desired separator. You can use

#Locale settings
import locale
locale.setlocale(locale.LC_ALL, "deu_deu")
import matplotlib as mpl
mpl.rcParams['axes.formatter.use_locale'] = True

#Generate sample plot
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,10,501)
y = np.sin(x)
ax = plt.subplot(111)
ax.plot(x,y)
ax.yaxis.set_major_formatter(y_format)  # set formatter to needed axis

plt.show()

to produce the same plot as in Andrey's solution, but you can be sure it behaves correctly also in corner-cases.

I think the question really refers to presenting say 300000 on the y-axis as 300,000.

To borrow from Andrey's answer, with a minor tweak,

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as tkr

def func(x, pos):  # formatter function takes tick label and tick position
   s = '{:0,d}'.format(int(x))
   return s


y_format = tkr.FuncFormatter(func)  # make formatter

x = np.linspace(0,10,501)
y = np.sin(x)
ax = plt.subplot(111)
ax.plot(x,y)
ax.yaxis.set_major_formatter(y_format)  # set formatter to needed axis

plt.show()

I would like to expand on Thorsten Kranz answer, it seems that matplotlib (2.02) may have a bug, in that it does not use the thousand sep field of the locale to do the separation of thousands. This happens even if set_locale(True) is used.

Therefore if you set the locale to the UK locale, it should still separate the thousands by a comma but it does not. It does it for the German locale since the decimal point is used.

UK ('English_United Kingdom.1252') Locale:

{'currency_symbol': '\xa3',
 'decimal_point': '.',
 'frac_digits': 2,
 'grouping': [3, 0],
 'int_curr_symbol': 'GBP',
 'int_frac_digits': 2,
 'mon_decimal_point': '.',
 'mon_grouping': [3, 0],
 'mon_thousands_sep': ',',
 'n_cs_precedes': 1,
 'n_sep_by_space': 0,
 'n_sign_posn': 3,
 'negative_sign': '-',
 'p_cs_precedes': 1,
 'p_sep_by_space': 0,
 'p_sign_posn': 3,
 'positive_sign': '',
 'thousands_sep': ','}

German ('German_Germany.1252') locale:

{'currency_symbol': '\x80',
 'decimal_point': ',',
 'frac_digits': 2,
 'grouping': [3, 0],
 'int_curr_symbol': 'EUR',
 'int_frac_digits': 2,
 'mon_decimal_point': ',',
 'mon_grouping': [3, 0],
 'mon_thousands_sep': '.',
 'n_cs_precedes': 0,
 'n_sep_by_space': 1,
 'n_sign_posn': 1,
 'negative_sign': '-',
 'p_cs_precedes': 0,
 'p_sep_by_space': 1,
 'p_sign_posn': 1,
 'positive_sign': '',
 'thousands_sep': '.'}

Edit: Looking at the code in the Scalar formatter, Matplotlib does not use the grouping flag:

def pprint_val(self, x):
"""The last argument should be True"""
    xp = (x - self.offset) / (10. ** self.orderOfMagnitude)
    if np.absolute(xp) < 1e-8:
        xp = 0
    if self._useLocale:
        return locale.format_string(self.format, (xp,)) # <-- there should be a True as the last argument to this method which sets to grouping to True
    else:
        return self.format % xp

I would like to post another solution here similar to the one presented by Thorsten Kranz.

Use the following first lines in your code:

import locale
locale.setlocale(locale.LC_ALL, "Portuguese_Brazil.1252")
import matplotlib as mpl
mpl.rcParams['axes.formatter.use_locale'] = True

This way, your code will be settled to Brazil standard text formating. I believe it could help you out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM