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]:
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
andyaxis
are attributes of the plotaxes
, for aseaborn.axisgrid.FacetGrid
type.- In the linked answer, the type is
matplotlib.axes._subplots.AxesSubplot
- In the linked answer, the type is
p
in thelambda
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'))
- 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')
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.
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), ',')))
Related Topics
How to Divide Each Column of Pandas Dataframe by a Series
Clicking Links With Python Beautifulsoup
How to Increase Dpi With Opencv
Converting a List into Comma Separated and Add Quotes in Python
Finding the Most Frequent Character in a String
Most Pythonic Way to Kill a Thread After Some Period of Time
How to Save a Pandas Dataframe Table as a Png
Move Seaborn Plot Legend to a Different Position
Split/Explode a Column of Dictionaries into Separate Columns With Pandas
Regex to Find Words Between Two Tags
Key Error When Selecting Columns in Pandas Dataframe After Read_Csv
How to Get Max Output from a While Loop
How to Select the Last Column of Dataframe
How to Name a File by a Variable Name in Python
Delete Every Non Utf-8 Symbols from String
How to Sum Dictionaries Values With Same Key Inside a List
Python: Pandas Pd.Read_Excel Giving Importerror: Install Xlrd >= 0.9.0 for Excel Support