110

How can I change the format of the numbers in the x-axis to be like 10,000 instead of 10000? Ideally, I would just like to do something like this:

x = format((10000.21, 22000.32, 10120.54), "#,###")

Here is the code:

import matplotlib.pyplot as plt

# create figure instance
fig1 = plt.figure(1)
fig1.set_figheight(15)
fig1.set_figwidth(20)

ax = fig1.add_subplot(2,1,1)

x = 10000.21, 22000.32, 10120.54

y = 1, 4, 15
ax.plot(x, y)

ax2 = fig1.add_subplot(2,1,2)

x2 = 10434, 24444, 31234
y2 = 1, 4, 9
ax2.plot(x2, y2)

fig1.show()
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
IcemanBerlin
  • 3,239
  • 6
  • 29
  • 33
  • 1
    Possible duplicate of [Matplotlib : Comma separated number format for axis](http://stackoverflow.com/questions/8271564/matplotlib-comma-separated-number-format-for-axis) – raphael Apr 24 '17 at 20:05

10 Answers10

116

Use , as format specifier:

>>> format(10000.21, ',')
'10,000.21'

Alternatively you can also use str.format instead of format:

>>> '{:,}'.format(10000.21)
'10,000.21'

With matplotlib.ticker.FuncFormatter:

...
ax.get_xaxis().set_major_formatter(
    matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))
ax2.get_xaxis().set_major_formatter(
    matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))
fig1.show()

enter image description here

falsetru
  • 357,413
  • 63
  • 732
  • 636
  • Thanks falsetru, adapting your code lines on matplot.ticker.FuncFormatter did the trick. – IcemanBerlin Sep 22 '14 at 14:05
  • @IcemanBerlin, You're welcome. BTW, I used `int` to remove decimals. If you want keep it, drop `int`. – falsetru Sep 22 '14 at 14:07
  • it was perfect, i did want to exclude decimals, i probably shouldnt have had them in the example. I did wonder what dropped them off though, so thanks again. – IcemanBerlin Sep 22 '14 at 14:20
82

The best way I've found to do this is with StrMethodFormatter:

import matplotlib as mpl
ax.yaxis.set_major_formatter(mpl.ticker.StrMethodFormatter('{x:,.0f}'))

For example:

import pandas as pd
import requests
import matplotlib.pyplot as plt
import matplotlib as mpl

url = 'https://min-api.cryptocompare.com/data/histoday?fsym=BTC&tsym=USDT&aggregate=1'
df = pd.DataFrame({'BTC/USD': [d['close'] for d in requests.get(url).json()['Data']]})

ax = df.plot()
ax.yaxis.set_major_formatter(mpl.ticker.StrMethodFormatter('{x:,.0f}'))
plt.show()

enter image description here

Alex
  • 12,078
  • 6
  • 64
  • 74
34

I always find myself on this same page everytime I try to do this. Sure, the other answers get the job done, but aren't easy to remember for next time! ex: import ticker and use lambda, custom def, etc.

Here's a simple solution if you have an axes named ax:

ax.set_yticklabels(['{:,}'.format(int(x)) for x in ax.get_yticks().tolist()])
Jarad
  • 17,409
  • 19
  • 95
  • 154
  • 2
    Nice… one-liner, and still fairly readable. Also, easy to modify, e.g. adding a dollar-sign: `...'${:,}'...` – ijoseph Aug 04 '19 at 22:14
  • I like this a lot, works great. I had to put it after my range setter, `ax.xaxis.set_major_locator(plt.MaxNLocator(20))` – avirr Nov 15 '19 at 22:13
  • Spits out an esoteric warning that I can't be bothered to look up or heed (`UserWarning: FixedFormatter should only be used together with FixedLocator`), but otherwise flawless. – ijoseph Dec 21 '22 at 20:37
20

Short answer without importing matplotlib as mpl

plt.gca().yaxis.set_major_formatter(plt.matplotlib.ticker.StrMethodFormatter('{x:,.0f}'))

Modified from @AlexG's answer

Tomas G.
  • 3,784
  • 25
  • 28
10

If you like it hacky and short you can also just update the labels

def update_xlabels(ax):
    xlabels = [format(label, ',.0f') for label in ax.get_xticks()]
    ax.set_xticklabels(xlabels)

update_xlabels(ax)
update_xlabels(ax2)
DanT
  • 3,960
  • 5
  • 28
  • 33
8

You can use matplotlib.ticker.funcformatter

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 = '%d' % x
    groups = []
    while s and s[-1].isdigit():
        groups.append(s[-3:])
        s = s[:-3]
    return s + ','.join(reversed(groups))

y_format = tkr.FuncFormatter(func)  # make formatter

x = np.linspace(0,10,501)
y = 1000000*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()

enter image description here

pad
  • 2,296
  • 2
  • 16
  • 23
  • adapted from [this](http://stackoverflow.com/questions/8271564/matplotlib-comma-separated-number-format-for-axis) answer. – pad Sep 22 '14 at 12:38
4
x = [10000.21, 22000.32, 10120.54]

You could use a list comprehension to make a list of labels, and then pass them the plt.xticks.

xlabels = [f'{label:,}' for label in x]
plt.xticks(x, xlabels)
jeffhale
  • 3,759
  • 7
  • 40
  • 56
3

If you want original values to appear in ticks, use

plt.xticks(ticks=plt.xticks()[0], labels=plt.xticks()[0])

This will prevent abbreviations like from 3000000 to 1.3 e5 etc. and will show 3000000 (the exact value) in ticks.

alercelik
  • 615
  • 7
  • 11
2

Easiest way in my opinion:

current_values = plt.gca().get_yticks()
plt.gca().set_yticklabels(['{:,.0f}'.format(x) for x in current_values])

From: https://queirozf.com/entries/matplotlib-examples-number-formatting-for-axes-labels

1

For non-comma separators, improving the accepted answer, below answer will use SEP as the separator.

SEP = '.'

ax.get_yaxis().set_major_formatter(
    matplotlib.ticker.FuncFormatter(
        lambda x, p: str.replace(format(int(x), ','), ',', SEP)
    )
)
Muhammad Yasirroni
  • 1,512
  • 12
  • 22