Reputation: 131
How can I annotate a seaborn pointplot with the values of col1 "A" "B" or "C" as a text, next to the points where they are drawn.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# Data
a = list("ABC") * 4
c = list("DE") * 6
score = np.random.randint(-5, 5, 12)
df = pd.DataFrame({"col1": a, "col2": c, "score": score})
print(df)
col1 col2 value
0 A D 3
1 B E 1
2 C D -3
3 A E -5
4 B D -4
5 C E -5
6 A D 2
7 B E -4
8 C D 4
9 A E 1
10 B D 3
11 C E -2
sns.pointplot(data=df, x="col2", y="value", hue='col1');
Desired outcome is with the labels A, B and C:
Upvotes: 1
Views: 439
Reputation: 80279
plt.text(x, y, 'a text')
places a text in a plot. The main problem is to find the exact positions and colors. To get a consistent order, it helps to explicitly make the columns categorical. The categorical numbering (0, 1, 2, ...
) is the same as matplotlib uses internally for its categorical axes.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
a = list("ABC") * 4
c = list("DE") * 6
score = np.random.randint(-5, 5, 12)
df = pd.DataFrame({"col1": a, "col2": c, "score": score})
df['col1'] = pd.Categorical(df['col1'])
df['col2'] = pd.Categorical(df['col2'])
palette = sns.color_palette("tab10")
ax = sns.pointplot(data=df, x="col2", y="score", hue='col1', palette=palette)
pos_after_last_x = len(df['col2'].cat.categories) - 1 + 0.05
last_x_cat = df['col2'].cat.categories[-1]
for cat, color in zip(df['col1'].cat.categories, palette):
mean_score = df[(df['col1'] == cat) & (df['col2'] == last_x_cat)]['score'].mean()
ax.text(pos_after_last_x, mean_score, cat, color=color)
plt.show()
Upvotes: 2