How to Format Seaborn/Matplotlib Axis Tick Labels from Number to Thousands or Millions (125,436 to 125.4K)

How to format seaborn/matplotlib axis tick labels from number to thousands or Millions? (125,436 to 125.4K)

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

set y-axis in millions

You can use a custom FuncFormatter like this:

from matplotlib.ticker import FuncFormatter
import matplotlib.pyplot as plt
def millions(x, pos):
'The two args are the value and tick position'
return '%1.1fM' % (x * 1e-6)


formatter = FuncFormatter(millions)

fig, ax = plt.subplots()
ax.yaxis.set_major_formatter(formatter)

Or you can even replace millions with the following functions to support all magnitudes:


def human_format(num, pos):
magnitude = 0
while abs(num) >= 1000:
magnitude += 1
num /= 1000.0
# add more suffixes if you need them
return '%.2f%s' % (num, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])

How to format the y- or x-axis labels in a seaborn FacetGrid

  • xaxis and yaxis are attributes of the plot axes, for a seaborn.axisgrid.FacetGrid type.
    • In the linked answer, the type is matplotlib.axes._subplots.AxesSubplot
  • p in the lambda expression is the tick label number.
  • seaborn: Building structured multi-plot grids
  • matplotlib: Creating multiple subplots
  • Tested and working with the following versions:
    • matplotlib v3.3.4
    • seaborn v0.11.1
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.ticker as tkr

sns.set(style="ticks")

# load data
exercise = sns.load_dataset("exercise")

# plot data
g = sns.catplot(x="time", y="pulse", hue="kind", col="diet", data=exercise)

# format the labels with f-strings
for ax in g.axes.flat:
ax.yaxis.set_major_formatter(tkr.FuncFormatter(lambda y, p: f'{y:.2f}: Oh baby, baby'))
ax.xaxis.set_major_formatter(tkr.FuncFormatter(lambda x, p: f'{x}: Is that your best'))

Sample Image

  • As noted in a comment by Patrick FitzGerald, the following code, without using tkr.FuncFormatter, also works to generate the previous plot.
  • See matplotlib.axis.Axis.set_major_formatter
# format the labels with f-strings
for ax in g.axes.flat:
ax.yaxis.set_major_formatter(lambda y, p: f'{y:.2f}: Oh baby, baby')
ax.xaxis.set_major_formatter(lambda x, p: f'{x}: Is that your best')

Seaborn / MatplotLib Axis and Data Values formatting: Hundreds, Thousands, and Millions

Matplotlib has an Engineering formatter for specifically this purpose. You can use it to format the axis (using set_major_formatter()) or to format any number, using EngFormatter.format_eng()

from matplotlib.ticker import EngFormatter
fmt = EngFormatter(places=0)

y = np.arange(1,10)
data = np.exp(3*y)
fig, ax = plt.subplots()
ax.set_xscale('log')
bars = ax.barh(y=y, width=data)
ax.xaxis.set_major_formatter(fmt)

for b in bars:
w = b.get_width()
ax.text(w, b.get_y()+0.5*b.get_height(),
fmt.format_eng(w),
ha='left', va='center')

enter image description here

I am using Python script in Power BI. How can I format the x axis tick labels and titles for a multiple seaborn 'displot'

I changed the approach and I came to the desired outcome by plotting every element separately.

import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

colors =["#FF0B04","#228800","#ffbb33"]
sns.set_palette(colors)

sns.set_context("notebook", font_scale=1.2, rc={"font.size":5, "axes.labelsize":12})
sns.set_style("ticks", {"xtick.major.size":8,"ytick.major.size":8})
current_palette = sns.color_palette(colors)

x, y, z= dataset["OverallTotalScore%"], dataset["Profit"], dataset["ClassificationChar"]


f, (ax1, ax2, ax3) = plt.subplots (1,3, figsize=(16, 6), sharey= True)
sns.despine(left=False, bottom=False, offset=0)

sns.histplot(x=y, hue=z, hue_order='A', stat="count", alpha = 1, palette = ['#228800'], kde=False, fill=True, legend=False, bins=50, ax=ax1)
sns.histplot(x=y, hue=z, hue_order='B', stat="count", alpha = 1, palette = ['#ffbb33'], kde=False, fill=True, legend=False, bins=50, ax=ax2)
sns.histplot(x=y, hue=z, hue_order='C', stat="count", alpha = 1, palette = ['#FF0B04'], kde=False, fill=True, legend=False, bins=50, ax=ax3)

ax1.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: '£{:,.0f}K'.format(x/1000)))
ax2.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: '£{:,.0f}K'.format(x/1000)))
ax3.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: '£{:,.0f}K'.format(x/1000)))

ax1.grid(b=True, which='major')
ax1.grid(b=True, which='minor')
ax2.grid(b=True, which='major')
ax2.grid(b=True, which='minor')
ax3.grid(b=True, which='major')
ax3.grid(b=True, which='minor')

ax1.legend().set_title('Class A')
ax2.legend().set_title('Class B')
ax3.legend().set_title('Class C')

plt.style.use("classic")
plt.tight_layout()
plt.show()

Tick labels for y axis are very long. How to truncate them in seaborn?

One idea could be to let the text in the labels roll like a marquee.

enter image description here

import matplotlib.pyplot as plt
import matplotlib.text
import matplotlib.animation

class Roller():
def __init__(self):
self.texts = []

def append(self, text, **kwargs):
RollingText.assimilate(text, **kwargs)
self.texts.append(text)

def roll(self, i=0):
for text in self.texts:
text.roll()

def ticklabelroll(self, i=0):
self.roll()
ticklabels = [t.get_text() for t in self.texts]
plt.gca().set_yticklabels(ticklabels)



class RollingText(matplotlib.text.Text):
n = 10
p = 0
def __init__(self, *args, **kwargs):
self.n = kwargs.pop("n", self.n)
matplotlib.text.Text(*args, **kwargs)
self.set_myprops()

def set_myprops(self, **kwargs):
self.fulltext = kwargs.get("fulltext", self.get_text())
self.n = kwargs.get("n", self.n)
if len(self.fulltext) <=self.n:
self.showntext = self.fulltext
else:
self.showntext = self.fulltext[:self.n]
self.set_text(self.showntext)

def roll(self, by=1):
self.p += by
self.p = self.p % len(self.fulltext)
if self.p+self.n <= len(self.fulltext):
self.showntext = self.fulltext[self.p:self.p+self.n]
else:
self.showntext = self.fulltext[self.p:] + " " + \
self.fulltext[0:(self.p+self.n) % len(self.fulltext)]
self.set_text(self.showntext)

@classmethod
def assimilate(cls, instance, **kwargs):
# call RollingText.assimilate(Text, n=10, ...)
instance.__class__ = cls
instance.set_myprops(**kwargs)

if __name__ == "__main__":
import pandas as pd
import seaborn as sns

fn = r"data\nutrition-facts-for-mcdonald-s-menu\menu.csv"
df = pd.read_csv(fn)

grouped = df.groupby(df["Protein"])
item = grouped["Item"].sum()
item_list = item.sort_index()
item_list = item_list[-20:]

fig, ax = plt.subplots(figsize=(10,7.5))
plt.subplots_adjust(left=0.3)

sns.barplot(item_list.index,item_list.values, ax=ax)

# create a Roller instance
r = Roller()
# append all ticklabels to the Roller
for tl in ax.get_yticklabels():
r.append(tl, n=25)

#animate the ticklabels
ani = matplotlib.animation.FuncAnimation(fig, r.ticklabelroll,
frames=36, repeat=True, interval=300)
ani.save(__file__+".gif", writer="imagemagick")
plt.show()

How do I get the x-axis lables to be hidden between every 5th tick so the graph looks cleaner in matplotlib?

Using plt.MaxNLocator() instead, places the ticks in the order that you needed:

import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns

# sets style of plot
plt.figure(figsize=(15,8))
sns.set(style='dark')
sns.set_context('talk')

year = [1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]

acres = [4156000, 4478188, 3036219, 4078894, 7120768, 4197309, 2652112, 4574389, 4658586, 4231996, 6689081, 3278565, 4278472, 2641166, 1915273, 2879095, 1791327, 5109926, 3152644, 3910913, 2986826, 5260825, 4814206, 2382036, 1323666, 1148409, 2896147, 2719162, 2447296, 5009290, 1827310, 4621621, 2953578, 2069929, 1797574, 4073579, 1840546, 6065998, 2856959, 1329704, 5626093, 7393493, 3570911, 7184712, 3960842, 8097880, 8689389, 9873745, 9328045, 5292468, 5921786, 3422724, 8711367, 9326238, 4319546, 3595613, 10125149, 5509995, 10026086, 8767492, 4664364]

df = pd.DataFrame({'year':year, 'acres':acres}) # did this to put the axis label

ax = sns.barplot(x=df['year'], y=df['acres'])

plt.ticklabel_format(style='plain', axis='y')
plt.xticks(rotation=45)
ax.xaxis.set_major_locator(plt.MaxNLocator(df['year'].shape[0]/4))

ax.get_yaxis().set_major_formatter(
mpl.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))

Sample Image



Related Topics



Leave a reply



Submit