3

I have a problem which I simplified as below, I would love if anyone suggest me the code in seaborn like what I want to achieve.

import matplotlib.pyplot as plt


a = [2000, 4000, 3000, 8000, 6000, 3000, 3000, 4000, 2000, 4000, 3000, 8000, 6000, 3000, 3000, 4000, 2000, 4000, 3000, 8000, 6000, 3000, 3000, 4000]
b = [0.8, 0.9, 0.83, 0.81, 0.86, 0.89, 0.89, 0.8, 0.8, 0.9, 0.83, 0.81, 0.86, 0.89, 0.89, 0.8, 0.8, 0.9, 0.83, 0.81, 0.86, 0.89, 0.89, 0.8]
c = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]

fig1, ax1 = plt.subplots(figsize=(12, 6))
ax12 = ax1.twinx()

ax1.bar(c, a)
ax12.plot(c, b, 'o-', color="red", markersize=12,
          markerfacecolor='Yellow', markeredgewidth=2, linewidth=2)
ax12.set_ylim(bottom=0, top=1, emit=True, auto=False)

plt.grid()
plt.show()

I am trying to achieve the labels in the center and vertical as shown in the following figure.

Desired output

tdy
  • 36,675
  • 19
  • 86
  • 83
Zeryab Hassan Kiani
  • 467
  • 1
  • 7
  • 18

1 Answers1

4

As of matplotlib 3.4.0, use Axes.bar_label:

  • label_type='center' places the labels at the center of the bars
  • rotation=90 rotates them 90 deg

Since this is a regular bar chart, we only need to label one bar container ax1.containers[0]:

ax1.bar_label(ax1.containers[0], label_type='center', rotation=90, color='white')

But if this were a grouped/stacked bar chart, we should iterate all ax1.containers:

for container in ax1.containers:
    ax1.bar_label(container, label_type='center', rotation=90, color='white')


seaborn version

I just noticed the question text asks about seaborn, in which case we can use sns.barplot and sns.pointplot. We can still use bar_label with seaborn via the underlying axes.

import pandas as pd
import seaborn as sns

# put the lists into a DataFrame
df = pd.DataFrame({'a': a, 'b': b, 'c': c})

# create the barplot and vertically centered labels
ax1 = sns.barplot(data=df, x='c', y='a', color='green')
ax1.bar_label(ax1.containers[0], label_type='center', rotation=90, color='white')

ax12 = ax1.twinx()
ax12.set_ylim(bottom=0, top=1, emit=True, auto=False)

# create the pointplot with x=[0, 1, 2, ...]
# this is because that's where the bars are located (due to being categorical)
sns.pointplot(ax=ax12, data=df.reset_index(), x='index', y='b', color='red')

tdy
  • 36,675
  • 19
  • 86
  • 83