44
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn as sns
import pandas as pd
sns.set(style="darkgrid")    
fig, ax = plt.subplots(figsize=(8, 5))    
palette = sns.color_palette("bright", 6)
g = sns.scatterplot(ax=ax, x="Area", y="Rent/Sqft", hue="Region", marker='o', data=df, s=100, palette= palette)
g.legend(bbox_to_anchor=(1, 1), ncol=1)
g.set(xlim = (50000,250000))

enter image description here

How can I can change the axis format from a number to custom format? For example, 125000 to 125.00K

Community
  • 1
  • 1
Vinay
  • 1,149
  • 3
  • 16
  • 28

5 Answers5

54

IIUC you can format the xticks and set these:

In[60]:
#generate some psuedo data
df = pd.DataFrame({'num':[50000, 75000, 100000, 125000], 'Rent/Sqft':np.random.randn(4), 'Region':list('abcd')})
df

Out[60]: 
      num  Rent/Sqft Region
0   50000   0.109196      a
1   75000   0.566553      b
2  100000  -0.274064      c
3  125000  -0.636492      d

In[61]:
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn as sns
import pandas as pd
sns.set(style="darkgrid")    
fig, ax = plt.subplots(figsize=(8, 5))    
palette = sns.color_palette("bright", 4)
g = sns.scatterplot(ax=ax, x="num", y="Rent/Sqft", hue="Region", marker='o', data=df, s=100, palette= palette)
g.legend(bbox_to_anchor=(1, 1), ncol=1)
g.set(xlim = (50000,250000))
xlabels = ['{:,.2f}'.format(x) + 'K' for x in g.get_xticks()/1000]
g.set_xticklabels(xlabels)

Out[61]: 

enter image description here

The key bit here is this line:

xlabels = ['{:,.2f}'.format(x) + 'K' for x in g.get_xticks()/1000]
g.set_xticklabels(xlabels)

So this divides all the ticks by 1000 and then formats them and sets the xtick labels

UPDATE Thanks to @ScottBoston who has suggested a better method:

ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: '{:,.2f}'.format(x/1000) + 'K'))

see the docs

EdChum
  • 376,765
  • 198
  • 813
  • 562
  • 9
    You can also, try using ticker.FuncFormatter: `ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: '{:,.2f}'.format(x/1000) + 'K'))` – Scott Boston Dec 12 '18 at 16:55
  • 3
    Note that the `ax.xaxis.set_major_formatter` approach doesn't work if you your figure is a `FacetGrid`. – Scott H Mar 30 '20 at 23:16
39

The canonical way of formatting the tick labels in the standard units is to use an EngFormatter. There is also an example in the matplotlib docs.

Also see Tick locating and formatting

Here it might look as follows.

import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn as sns
import pandas as pd

df = pd.DataFrame({"xaxs" : np.random.randint(50000,250000, size=20),
                   "yaxs" : np.random.randint(7,15, size=20),
                   "col"  : np.random.choice(list("ABC"), size=20)})
    
fig, ax = plt.subplots(figsize=(8, 5))    
palette = sns.color_palette("bright", 6)
sns.scatterplot(ax=ax, x="xaxs", y="yaxs", hue="col", data=df, 
                marker='o', s=100, palette="magma")
ax.legend(bbox_to_anchor=(1, 1), ncol=1)
ax.set(xlim = (50000,250000))

ax.xaxis.set_major_formatter(ticker.EngFormatter())

plt.show()

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • FYI: for anyone running this code with `matplotlib 3.3.1` and `seaborn 0.10.1`, you'll get `ValueError: zero-size array to reduction operation minimum which has no identity`. To resolve that issue, change `hue='col'` to `hue=df.col.tolist()`. This is a known bug. – Trenton McKinney Sep 02 '20 at 19:04
10

Using Seaborn without importing matplotlib:

import seaborn as sns
sns.set()

chart = sns.relplot(x="x_val", y="y_val", kind="line", data=my_data)

ticks = chart.axes[0][0].get_xticks()

xlabels = ['$' + '{:,.0f}'.format(x) for x in ticks]

chart.set_xticklabels(xlabels)
chart.fig

Thank you to EdChum's answer above for getting me 90% there.

Boris Yakubchik
  • 3,861
  • 3
  • 34
  • 41
  • 2
    If you want to use formatters (https://matplotlib.org/stable/api/ticker_api.html) and not import matplotlib, you can use: `chart.ax.xaxis.set_major_formatter(formatter)` – Nicolas Malbran Jun 11 '22 at 11:01
5

Here's how I'm solving this: (similar to ScottBoston)

from matplotlib.ticker import FuncFormatter

f = lambda x, pos: f'{x/10**3:,.0f}K'
ax.xaxis.set_major_formatter(FuncFormatter(f))
Yaakov Bressler
  • 9,056
  • 2
  • 45
  • 69
0

We could used the APIs: ax.get_xticklabels() , get_text() and ax.set_xticklabels do it.

e.g,

xlabels = ['{:.2f}k'.format(float(x.get_text().replace('−', '-')))/1000 for x in g.get_xticklabels()]
g.set_xticklabels(xlabels)
Ian Thompson
  • 2,914
  • 2
  • 18
  • 31
fooweel
  • 51
  • 1
  • 3
  • 2
    Code-only answers are strongly discouraged. Please [include an explanation](https://meta.stackoverflow.com/q/392712/13138364) of how and why this solves the problem. This will help future readers to better understand your solution. - [From Review](https://stackoverflow.com/review/low-quality-posts/30166897) – tdy Oct 25 '21 at 02:42