Reputation: 2479
The default Seaborn barplot almost works for me albeit a few details. It is shown below:
Please look at the 'text' annotation alongside and to the right of each bar. There are a few things that I would like to improve upon:
The last bar does NOT show the annotation for some reason. I do not know how to fix that.
There is no space between the edges of bars and the top and bottom X axes. I would like to put some space in there.
Is there anyway that the widths of the bars can be increased?
I would also like to increase the distance between the 'tallest' bar and the right Y axis, since I am planning on adding text than just the Thickness numbers corresponding to their X axis values. It would be something like 105.65 (42.54%) if you look at the bar corresponding to Red0 category of the HRA. That will clearly push it 'over' the edge of right Y axis. Is there a way to put some more distance between its peak and the max X axis value? So for instance, if I could set it to the Max height of the bars (easy to calculate) plus a certain amount.
If I could take care of those details, it would make it perfect!
Here is the snippet of my code that is relevant to the questions above:
sns.set_style('whitegrid')
sns.set(font_scale=0.8)
thickness = []
for hra_color in df_hra_colors['hra']:
thickness.append(grouped.get_group(hra_color).count()['hra'] * mult)
df_hra_colors['thickness'] = thickness
ax = sns.barplot(x='thickness', y='hra', data=df_hra_colors,
palette=df_hra_colors['hex'].tolist())
ax.set_xlabel("Thickness")
ax.set_ylabel("HRA")
ax.set_title("What an Awesome Plot!")
for p in ax.patches:
ax.annotate("%.2f" % p.get_width(), (p.get_x() + p.get_width(), p.get_y() + 1.2),
xytext=(5, 10), textcoords='offset points')
plt.show()
Here is a minimal, complete verifiable example as requested:
""" Minimal program for demonstration """
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
def main():
sns.set_style('whitegrid')
sns.set(font_scale=0.8)
# plt.rcParams['figure.figsize'] = (10,10)
df_hra_colors = pd.DataFrame({
'hra': ['red', 'green', 'blue'],
'hex': ['#cc0000', '#40ff00', '#0000ff']
})
thickness = [1, 2, 3]
thick_sum = sum(thickness)
df_hra_colors['thickness'] = thickness
ax = sns.barplot(x='thickness', y='hra', data=df_hra_colors,
palette=df_hra_colors['hex'].tolist())
plt.xlim(0, max(thickness) + 30)
ax.set_xlabel("Thickness")
ax.set_ylabel("HRA")
ax.set_title("What an Awesome Plot!")
for i, p in enumerate(ax.patches):
ax.annotate("%.2f (%.2f)%%" % (p.get_width(), thickness[i] / thick_sum * 100.0),
(p.get_x() + p.get_width(), p.get_y() + 1),
xytext=(5, 10), textcoords='offset points')
plt.show()
if __name__ == "__main__":
main()
I then changed the line that adds 1 to p.get_y() to add 0.5 instead as shown below:
for i, p in enumerate(ax.patches):
ax.annotate("%.2f (%.2f)%%" % (p.get_width(), thickness[i] / thick_sum * 100.0),
(p.get_x() + p.get_width(), p.get_y() + 0.5),
xytext=(5, 10), textcoords='offset points')
So the annotated text was hidden because of the offset. Using this knowledge, I could adjust my original script to show the annotated text in the last bar. But this leads to additional question. How do you adjust the code to be consistent when you do not know the number of bars in advance?
Your answer 2 works fine. Thank you.
Number 3 did not work for me since I am using sns.barplot. Python does not like the width parameter in the call to barplot.
Number 4 works fine. Thank you.
Thank you for your help with my questions.
Upvotes: 3
Views: 9792
Reputation: 339725
Concerning the first point, we need a minimal, complete, verifiable example.
In order to put space between the edge bars and the axes, one can adjust the limits of the axes. ax.set_ylim(-1,N)
, where N
is the number of bars.
The width of the bars can be set with the width
argument of plt.bar
.
plt.bar(..., width=1)
; or, for horizontal bars, use the height
argument. The seaborn bar plot does not allow to set the width or height.
Same as 2, just with ax.set_xlim(0,barmax*1.4)
, where barmax
is the maximum length of the bar.
Upvotes: 1