1

I'm trying to set the x-ticks labels for every 10 years. However, when the x-ticks range is set, all of the bars are compressed to the left side of the figure.

DataFrame Sample

   Temperature  Year
0           82  1900
1           52  1901
2           33  1902
3           91  1903
4           44  1904

Code

import pandas as pd
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt

# random sample data
np.random.seed(365)
df = pd.DataFrame({'Temperature': np.random.randint(0, 100, 124), 'Year': range(1900, 2024)})

# setting xticks based on the min and max year
sns.barplot(data=df, x='Year', y='Temperature')
_ = plt.xticks(range(df.Year.min(), df.Year.max(), 10))

enter image description here

How can I fix the barplot so the x-axis labels have the correct range, and the bars are positioned correctly?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Sonny Parlin
  • 931
  • 2
  • 13
  • 28

1 Answers1

1
  • The axis ticks of a seaborn.barplot, and a pandas.DataFrame.plot with kind='bar', are indexed from 0. The xtick label is just text, and is not representative of the tick position.
    • matplotlib.pyplot.bar and matplotlib.axes.Axes.bar are indexed based on the value passed to the x-axis, if it's not a string data type.
    • seaborn is a high-level API for matplotlib, and pandas.DataFrame.plot uses matplotlib as the default backend.
    • The same applies to horizontal bars, and to other categorical plot methods, such as violinplot, swarmplot, stripplot, and boxplot.
  • Using plt.gca().get_xticklabels(), or ax.get_xticklabels(), will show the ticks and the associated labels.
  • Set the xtick range from 0 to the len(df).
# setting xticks based on the ticks being 0 indexed
# color was set to a single color, because the husl color did not encode any information
sns.barplot(data=df, x='Year', y='Temperature', color='tab:blue', width=0.3)
_ = plt.xticks(range(0, len(df), 12))

enter image description here

df.plot(kind='bar', x='Year', rot=0)
_ = plt.xticks(range(0, len(df), 12))

enter image description here

plt.bar(height='Temperature', x='Year', data=df)
_ = plt.xticks(range(df.Year.min(), df.Year.max() + 1, 10))

enter image description here


  • This applies to other categorical plots:
    • violinplot, swarmplot, stripplot, boxplot, and horizontal barplot.
flights = sns.load_dataset('flights')

fig, ax = plt.subplots(2, 3, figsize=(12, 8), sharex=False, sharey=False, tight_layout=True)

ax = ax.flat

sns.violinplot(data=flights, x='year', y='passengers', color='tab:pink', ax=ax[0])
ax[0].set_xticks(range(0, len(df.year.unique()), 2))

sns.swarmplot(data=flights, x='year', y='passengers', size=3, ax=ax[1])
ax[1].set_xticks(range(0, len(df.year.unique()), 2))

sns.stripplot(data=flights, x='year', y='passengers', size=3, ax=ax[2])
ax[2].set_xticks(range(0, len(df.year.unique()), 2))

sns.boxplot(data=flights, x='year', y='passengers', color='tab:pink', ax=ax[3])
ax[3].set_xticks(range(0, len(df.year.unique()), 2))

sns.barplot(data=flights, y='year', x='passengers', color='tab:pink', orient='h', ax=ax[5])
ax[5].set_yticks(range(0, len(df.year.unique()), 2))

ax[4].remove()

plt.show()

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158