Michele
Michele

Reputation: 283

tick frequency when using seaborn/matplotlib boxplot

I am plotting with seaborn a series of boxplots with

sns.boxplot(full_array)

where full_array contains 200 arrays. Therefore, I have 200 boxplots and ticks on the x-axis from 0 to 200.

The xticks are too close to each other and I would like to show only some of them, for instance, a labeled xtick every 20, or so.

I tried several solutions as those mentioned here but they did not work.

Every time I sample the xticks, I get wrong labels for the ticks, as they get numbered from 0 to N, with unit spacing.

For instance, with the line

ax.xaxis.set_major_locator(ticker.MultipleLocator(20))

I get a labelled xtick every 20 but the labels are 1, 2, 3, 4 instead of 20, 40, 60, 80...

Upvotes: 28

Views: 44153

Answers (2)

cottontail
cottontail

Reputation: 23391

In modern versions of seaborn (v.0.12.0 etc.), the ticks' values are set by FuncFormatter, so OP's initial attempt works fine.

import numpy as np
import seaborn as sns
from matplotlib.ticker import MultipleLocator

data = np.random.rand(20,30)
ax = sns.boxplot(data=data)

ax.xaxis.get_major_locator()                    # <matplotlib.ticker.FixedLocator at 0x2221f657340>
ax.xaxis.get_major_formatter()                  # <matplotlib.ticker.FuncFormatter at 0x2221f8e2a00>

ax.xaxis.set_major_locator(MultipleLocator(5))  # show every 5th tick

Another way that works is to simply set the xticks by selecting every 5th.

ax = sns.boxplot(data=data);
ax.set_xticks(ax.get_xticks()[::5]);            # show every 5th tick

result

Upvotes: 2

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339660

The seaborn boxplot uses a FixedLocator and a FixedFormatter, i.e.

print ax.xaxis.get_major_locator()
print ax.xaxis.get_major_formatter()

prints

<matplotlib.ticker.FixedLocator object at 0x000000001FE0D668>
<matplotlib.ticker.FixedFormatter object at 0x000000001FD67B00>

It's therefore not sufficient to set the locator to a MultipleLocator since the ticks' values would still be set by the fixed formatter.

Instead you would want to set a ScalarFormatter, which sets the ticklabels to correspond to the numbers at their position.

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn.apionly as sns
import numpy as np

ax = sns.boxplot(data = np.random.rand(20,30))

ax.xaxis.set_major_locator(ticker.MultipleLocator(5))
ax.xaxis.set_major_formatter(ticker.ScalarFormatter())

plt.show()

enter image description here

Upvotes: 41

Related Questions