Issue
Let us consider the following example (from Seaborn documentation):
titanic = sns.load_dataset("titanic")
fg = sns.catplot(x="age", y="embark_town",
hue="sex", row="class",
data=titanic[titanic.embark_town.notnull()],
orient="h", height=2, aspect=3, palette="Set3",
kind="violin", dodge=True, cut=0, bw=.2)
Output:
I want to change the tick labels on the y axis, for example by prepending a number in parenthesis: (1) Southampton, (2) Cherbourg, (3) Queenstown. I have seen this answer, and I have tried to use a FuncFormatter
, but I obtain a strange result. Here is my code:
titanic = sns.load_dataset("titanic")
fg = sns.catplot(x="age", y="embark_town",
hue="sex", row="class",
data=titanic[titanic.embark_town.notnull()],
orient="h", height=2, aspect=3, palette="Set3",
kind="violin", dodge=True, cut=0, bw=.2)
from matplotlib.ticker import FuncFormatter
for ax in fg.axes.flat:
ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: f'({1 + pos}) {x}'))
And here is the output:
It looks like x
is the same as pos
in the lambda
. I was expecting x
to be the value of the tick label (i.e. Southampton, Cherbourg, Queenstown). What am I doing wrong?
Software versions:
matplotlib 3.4.3
seaborn 0.11.2
Solution
- Similar to the answers for How to rotate xticklabels in a seaborn catplot, but requiring customized text for each tick of each subplot.
- Text labels work differently than numeric labels that are in the other example. Numeric labels match the tick position, but that is not the case for text labels.
.get_yticklabels()
gets[Text(0, 0, 'Southampton'), Text(0, 1, 'Cherbourg'), Text(0, 2, 'Queenstown')]
for each subplot- As shown below, extract the text and position, and the use
.set_yticklabels
to set the new text label - Tested in
python 3.8.12
,matplotlib 3.4.3
,seaborn 0.11.2
import seaborn as sns
titanic = sns.load_dataset("titanic")
fg = sns.catplot(x="age", y="embark_town",
hue="sex", row="class",
data=titanic[titanic.embark_town.notnull()],
orient="h", height=2, aspect=3, palette="Set3",
kind="violin", dodge=True, cut=0, bw=.2)
for ax in fg.axes.flat: # iterate through each subplot
labels = ax.get_yticklabels() # get the position and text for each subplot
for label in labels:
_, y = label.get_position() # extract the y tick position
txt = label.get_text() # extract the text
txt = f'({y + 1}) {txt}' # update the text string
label.set_text(txt) # set the text
ax.set_yticklabels(labels) # update the yticklabels
Answered By - Trenton McKinney
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.