I am working with the excellent seaborn.objects
module in the most recent version of seaborn.
I would like to produce a plot:
Rotating x-axis labels is not directly supported within seaborn.objects
(and standard stuff like plt.xticks()
after making the graph doesn't work), but the documentation suggests doing it using the .on()
method. .on()
takes a matplotlib figure/subfigure or axis object and builds on top of it. As I pointed out in my answer to this question, the following code works to rotate axis labels:
import seaborn.objects as so
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({'a':[1,2,3,4],
'b':[5,6,7,8],
'c':['a','a','b','b']})
fig, ax = plt.subplots()
ax.xaxis.set_tick_params(rotation=90)
(so.Plot(df, x = 'a', y = 'b')
.add(so.Line())
.on(ax))
However, if I add facets by changing the graph code to
(so.Plot(df, x = 'a', y = 'b')
.add(so.Line())
.on(ax)
.facet('c'))
I get the error Cannot create multiple subplots after calling Plot.on with a <class 'matplotlib.axes._axes.Axes'> object. You may want to use a <class 'matplotlib.figure.SubFigure'> instead.
However, if I follow the instruction, and instead use the fig
object, rotating the axes in that, I get a strange dual x-axis, one with rotated labels unrelated to the data, and the actual graph's labels, unrotated:
fig, ax = plt.subplots()
plt.xticks(rotation = 90)
(so.Plot(df, x = 'a', y = 'b')
.add(so.Line())
.on(fig)
.facet('c'))
How can I incorporate rotated axis labels with facets?
You're ending up with multiple axes plotted on top of each other. Note the parameter description for Plot.on
:
Passing
matplotlib.axes.Axes
will add artists without otherwise modifying the figure. Otherwise, subplots will be created within the space of the givenmatplotlib.figure.Figure
ormatplotlib.figure.SubFigure
.
Additionally, the pyplot
functions (i.e. plt.xticks
) only operate on the "current" axes, not all axes in the current figure.
So, two step solution:
Plot
Example:
fig = plt.figure()
(so.Plot(df, x = 'a', y = 'b')
.add(so.Line())
.on(fig)
.facet('c')
.plot()
)
for ax in fig.axes:
ax.tick_params("x", rotation=90)
Note that it will likely become possible to control tick label rotation directly through the Plot
API, although rotating tick labels (especially to 90 degrees) is often not the best way to make overlapping labels readable.