I'd like to adapt my plotting code in order to show min/max bar as depicted in the figure below:
My code is:
from datetime import datetime, timedelta
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("white")
sns.set_style('darkgrid',{"axes.facecolor": ".92"}) # (1)
sns.set_context('notebook')
Delay = ['S1', 'S2', 'S3', 'S4']
Time = [87, 66, 90, 55]
df = pd.DataFrame({'Delay':Delay,'Time':Time})
print("Accuracy")
display(df) # in jupyter
fig, ax = plt.subplots(figsize = (8,6))
x = Delay
y = Time
plt.xlabel("Delay", size=14)
plt.ylim(-0.3, 100)
width = 0.1
for i, j in zip(x,y):
ax.bar(i,j, edgecolor = "black",
error_kw=dict(lw=1, capsize=1, capthick=1))
ax.set(ylabel = 'Accuracy')
from matplotlib import ticker
ax.yaxis.set_major_locator(ticker.MultipleLocator(10))
plt.savefig("Try.png", dpi=300, bbox_inches='tight')
The code produce this figure:
The min/max I want to add is for:
87 (60-90)
66 (40-70)
90 (80-93)
55 (23-60)
Thanks in advance for help.
seaborn.barplot
and ax.bar
.matplotlib.pyplot.errorbar
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# set edgecolor param (this is a global setting, so only set it once)
plt.rcParams["patch.force_edgecolor"] = True
# setup the dataframe
Delay = ['S1', 'S2', 'S3', 'S4']
Time = [87, 66, 90, 55]
df = pd.DataFrame({'Delay':Delay,'Time':Time})
# create a dict for the errors
error = {87: {'max': 90,'min': 60}, 66: {'max': 70,'min': 40}, 90: {'max': 93,'min': 80}, 55: {'max': 60,'min': 23}}
seaborn.barplot
seaborn.barplot
will add error bars automatically, as shown in the examples at the link. However, this is specific to using many data points. In this case, a value is being specified as the error, the error is not being determined from the data.
capsize
parameter can be specified, to add horizontal lines at the top and bottom of the error bar.# plot the figure
fig, ax = plt.subplots(figsize=(8, 6))
sns.barplot(x='Delay', y='Time', data=df, ax=ax)
# add the lines for the errors
for p in ax.patches:
x = p.get_x() # get the bottom left x corner of the bar
w = p.get_width() # get width of bar
h = p.get_height() # get height of bar
min_y = error[h]['min'] # use h to get min from dict z
max_y = error[h]['max'] # use h to get max from dict z
plt.vlines(x+w/2, min_y, max_y, color='k') # draw a vertical line
yerr
parameter can be used to explicitly provide errors to the API.
yerr
expects the values to be in relation to the top of the bar
S1
is 87, with min
or 60 and max
of 90. Therefore, ymin
is 27, (87-60), and ymax
is 3, (90-87).seaborn.barplot
capsize
parameter doesn't seem to work with yerr
, so you must set the matplotlib
'errorbar.capsize'
rcParmas
. See Matplotlib Errorbar Caps Missing
# set capsize param (this is a global setting, so only set it once)
plt.rcParams['errorbar.capsize'] = 10
# create dataframe as shown by gepcel
Delay = ['S1', 'S2', 'S3', 'S4']
Time = [87, 66, 90, 55]
_min = [60, 40, 80, 23]
_max = [90, 70, 93, 60]
df = pd.DataFrame({'Delay':Delay,'Time':Time, 'Min': _min, 'Max': _max})
# create ymin and ymax
df['ymin'] = df.Time - df.Min
df['ymax'] = df.Max - df.Time
# extract ymin and ymax into a (2, N) array as required by the yerr parameter
yerr = df[['ymin', 'ymax']].T.to_numpy()
# plot with error bars
fig, ax = plt.subplots(figsize=(8, 6))
sns.barplot(x='Delay', y='Time', data=df, yerr=yerr, ax=ax)
pandas.DataFrame.plot.bar
fig, ax = plt.subplots(figsize=(8, 6))
df.plot.bar(x='Delay', ax=ax)
for p in ax.patches:
x = p.get_x() # get the bottom left x corner of the bar
w = p.get_width() # get width of bar
h = p.get_height() # get height of bar
min_y = error[h]['min'] # use h to get min from dict z
max_y = error[h]['max'] # use h to get max from dict z
plt.vlines(x+w/2, min_y, max_y, color='k') # draw a vertical line
ax.bar
fig, ax = plt.subplots(figsize=(8, 6))
ax.bar(x='Delay', height='Time', data=df)
for p in ax.patches:
x = p.get_x() # get the bottom left x corner of the bar
w = p.get_width() # get width of bar
h = p.get_height() # get height of bar
min_y = error[h]['min'] # use h to get min from dict z
max_y = error[h]['max'] # use h to get max from dict z
plt.vlines(x+w/2, min_y, max_y, color='k') # draw a vertical line
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With