I am trying to display a count plot using seaborn, but the width of the bars is very high and the plot doesn't look nice. To counter it I change the width of the plot using the following code snippet:
sns.set()
fig,ax = plt.subplots(figsize=(10,4))
sns.countplot(x=imdb_data["label"],ax=ax)
for patch in ax.patches:
height = p.get_height()
width = patch.get_width
p.set_height(height*0.8)
patch.set_width(width*0.4)
x = p.get_x()
ax.text(x = x+new_width/2.,y= new_height+4,s = height,ha="center")
ax.legend(labels=("Negative","Positive"),loc='lower right')
plt.show()
But upon doing so the x-tick labels get shifted and the plot looks something like as shown in the attached image.
How should I change the width that, the x-tick location also, change automatically as per the new width of the bar ? . Also the legend is not being displayed properly. I used the below snippet to add the legend:
plt.legend(labels=['Positive','Negative'],loc='lower right')
Please help me out.
To keep the bar centered, you also need to change the x
position with half the difference of the old and new width. Changing the height doesn't seem to be a good idea, as then the labels on the y-axis get mismatched. If the main reason to change the height is to make space for the text, it would be easier to change the y
limits, e.g. via ax.margins()
. Aligning the text vertically with 'bottom'
allows leaving out the arbitrary offset for the y
position.
The labels for the legend can be set via looping through the patches and setting the labels one by one. As the x-axis already has different positions for each bar, it might be better to leave out the legend and change the x tick labels?
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
sns.set()
imdb_data = pd.DataFrame({"label": np.random.randint(0, 2, 7500)})
fig, ax = plt.subplots(figsize=(10, 4))
sns.countplot(x=imdb_data["label"], ax=ax)
for patch, label in zip(ax.patches, ["Negative", "Positive"]):
height = patch.get_height()
width = patch.get_width()
new_width = width * 0.4
patch.set_width(new_width)
patch.set_label(label)
x = patch.get_x()
patch.set_x(x + (width - new_width) / 2)
ax.text(x=x + width/2, y=height, s=height, ha='center', va='bottom')
ax.legend(loc='lower right')
ax.margins(y=0.1)
plt.tight_layout()
plt.show()
PS: To change the x tick labels, so they can be used instead of the legend, add
ax.set_xticklabels(['negative', 'positive'])
and leave out the ax.legend()
and patch.set_label(label)
lines.
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