I have the following dataframe:
data = {'Value':[6.25, 4.55, 4.74, 1.36, 2.56, 1.4, 3.55, 3.21, 3.2, 3.65, 3.45, 3.86, 13.9, 10.3, 15],
'Name':['Peter', 'Anna', 'Luke',
'Peter', 'Anna', 'Luke',
'Peter', 'Anna', 'Luke',
'Peter', 'Anna', 'Luke',
'Peter', 'Anna', 'Luke'],
'Param': ['Param1', 'Param1', 'Param1',
'Param2', 'Param2', 'Param2',
'Param3', 'Param3', 'Param3',
'Param4', 'Param4', 'Param4',
'Param5', 'Param5', 'Param5'],
'error': [2.55, 1.24, 0, 0.04, 0.97, 0, 0.87, 0.7, 0, 0.73, 0.62, 0, 0, 0, 0]}
df = pd.DataFrame(data)
I'd like to add errorbars (pre-defined in the error column) to the bar plot, but I can't seem to get the x-coordinates right? It shows errorbars for Param5
but there are no errors for Param5
? Also for Luke
, there are no errors, but in Param1
an errorbar is plotted.
plt.figure()
ax = sns.barplot(x = 'Param', y = 'Value', data = df, hue = 'Name', palette = sns.color_palette('CMRmap_r', n_colors = 3))
x_coords = [p.get_x() 0.5*p.get_width() for p in ax.patches]
y_coords = [p.get_height() for p in ax.patches]
plt.errorbar(x=x_coords, y=y_coords, yerr=df["error"], fmt="none", c= "k")
CodePudding user response:
The bars in ax.patches
come ordered by hue
value. To get the bars and the dataframe in the same order, the dataframe could be sorted first by Name
and then by Param
:
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd
data = {'Value': [6.25, 4.55, 4.74, 1.36, 2.56, 1.4, 3.55, 3.21, 3.2, 3.65, 3.45, 3.86, 13.9, 10.3, 15],
'Name': ['Peter', 'Anna', 'Luke',
'Peter', 'Anna', 'Luke',
'Peter', 'Anna', 'Luke',
'Peter', 'Anna', 'Luke',
'Peter', 'Anna', 'Luke'],
'Param': ['Param1', 'Param1', 'Param1',
'Param2', 'Param2', 'Param2',
'Param3', 'Param3', 'Param3',
'Param4', 'Param4', 'Param4',
'Param5', 'Param5', 'Param5'],
'error': [2.55, 1.24, 0, 0.04, 0.97, 0, 0.87, 0.7, 0, 0.73, 0.62, 0, 0, 0, 0]}
df = pd.DataFrame(data)
df = df.sort_values(['Name', 'Param'])
plt.figure()
ax = sns.barplot(x='Param', y='Value', data=df, hue='Name', palette='CMRmap_r')
x_coords = [p.get_x() 0.5 * p.get_width() for p in ax.patches]
y_coords = [p.get_height() for p in ax.patches]
ax.errorbar(x=x_coords, y=y_coords, yerr=df["error"], fmt="none", c="k")
plt.show()
PS: Note that by default, the columns are sorted alphabetically. If you want to maintain the original order, you can make the column categorical via pd.Categorical(df['Name'], df['Name'].unique())
.
df = pd.DataFrame(data)
df['Name'] = pd.Categorical(df['Name'], df['Name'].unique())
df['Param'] = pd.Categorical(df['Param'], df['Param'].unique())
df = df.sort_values(['Name', 'Param'])