Reputation: 45
I couldn't expand bars height to their percentage how can I do that? I'm getting confused...
I don't want to see the percentages of the bars, I want the values (40,40,40,40,40,33,17).
I want 7 bars with height of their percentage, but containers on bars should have their value name. For example n=40 in my problem; First bar has the value of 40. So this bars top should at %100 level, but container must wrote as 40.
Also another example; last (Tiktok bar) bar has the value of 17 so container should say 17 but the bar should be at the height of %42.5
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.ticker as mtick
plt.figure(figsize=(18,11),dpi=100)
sns.set_theme (style="whitegrid", palette="tab20b")
x_ekseni= ['İlgili Sosyal Medya Hesapları']
Website= [40]
Twitter= [40]
Facebook= [40]
Instagram= [40]
Youtube= [40]
Linkedin= [33]
Tiktok= [17]
index=x_ekseni
df = pd.DataFrame({'Website': Website,
'Twitter': Twitter,
'Facebook': Facebook,
'Instagram': Instagram,
'Youtube': Youtube,
'Linkedin': Linkedin,
'Tiktok': Tiktok}, index=index)
df
Website Twitter Facebook Instagram Youtube Linkedin Tiktok
İlgili Sosyal Medya Hesapları 40 40 40 40 40 33 17
ax = df.plot.bar(stacked=False,edgecolor='white',width = 2.5,linewidth=0.5)
# iterate through the containers
for c in ax.containers:
# get the current segment label (a string); corresponds to column / legend
col = c.get_label()
labels = df[col].replace(0, '')
# add the annotation
ax.bar_label(c, labels=labels, label_type='center', fontweight='bold', color='white',fontsize=10)
plt.title("İstanbul'daki Belediyelerin Sosyal Medya Kullanımı", fontsize=11, fontweight=0, color="black", loc="center")
ax.set_ylabel("İldeki Tüm Belediyeler İçinde Yüzde (n=40)", fontsize= 10)
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
plt.xticks(rotation=0,fontsize=8)
plt.yticks(rotation=0,fontsize=8)
plt.ylim(0,100)
ax.legend(frameon=True, fontsize=8)
Upvotes: 2
Views: 1263
Reputation: 62523
python 3.11.2
, pandas 2.0.0
, matplotlib 3.7.1
, seaborn 0.12.2
labels=
parameter in .bar_label
.import pandas as pd
import matplotlib.ticker as tkr
import matplotlib.pyplot as plt
import seaborn as sns
# test dataframe
data = {'Website': [40], 'Twitter': [40], 'Facebook': [40], 'Instagram': [40], 'Youtube': [40], 'Linkedin': [33], 'Tiktok': [17]}
df = pd.DataFrame(data, index=['İlgili Sosyal Medya Hesapları'])
# transpose df from a wide to a long form
df = df.T
# add a percent column
df['per'] = df.div(df.sum()).mul(100).round(2)
df
İlgili Sosyal Medya Hesapları per
Website 40 16.0
Twitter 40 16.0
Facebook 40 16.0
Instagram 40 16.0
Youtube 40 16.0
Linkedin 33 13.2
Tiktok 17 6.8
pandas.DataFrame.plot
with kind='bar'
# plot percent column
ax = df.plot(kind='bar', y='per', rot=0, figsize=(10, 7), ylabel='', legend=False)
# add the annotations; there's only 1 container of 7 artists
# iterating through the containers is only necessary for grouped or stacked bars, which have multiple containers
ax.bar_label(ax.containers[0], labels=df['İlgili Sosyal Medya Hesapları'].replace(0, ''), label_type='center', fontweight='bold', color='white', fontsize=10)
ax.set_title("İstanbul'daki Belediyelerin Sosyal Medya Kullanımı", fontsize=11, fontweight=0, color="black", loc="center")
ax.set_ylabel("İldeki Tüm Belediyeler İçinde Yüzde (n=40)", fontsize= 10)
ax.set_xlabel(df.columns[0], fontsize= 10)
ax.yaxis.set_major_formatter(tkr.PercentFormatter())
ax.tick_params(axis='both', which='major', labelsize=8)
_ = ax.set_ylim(0, 100)
seaborn.barplot
plt.figure(figsize=(10, 7))
# plot df, but the index must be reset
ax = sns.barplot(data=df.reset_index(), x='index', y='per')
ax.bar_label(ax.containers[0], labels=df['İlgili Sosyal Medya Hesapları'].replace(0, ''), label_type='center', fontweight='bold', color='white', fontsize=10)
ax.set_title("İstanbul'daki Belediyelerin Sosyal Medya Kullanımı", fontsize=11, fontweight=0, color="black", loc="center")
ax.set_ylabel("İldeki Tüm Belediyeler İçinde Yüzde (n=40)", fontsize= 10)
ax.set_xlabel(df.columns[0], fontsize= 10)
ax.yaxis.set_major_formatter(tkr.PercentFormatter())
ax.tick_params(axis='both', which='major', labelsize=8)
_ = ax.set_ylim(0, 100)
n=40
, use the following to calculate the 'per'
column.# an arbitrary value
n = 40
df['per'] = df.div(n, axis=0).mul(100).round(2)
# or
# the max value in the column
df['per'] = df.div(df.iloc[:, 0].max(), axis=0).mul(100).round(2)
İlgili Sosyal Medya Hesapları per
Website 40 100.0
Twitter 40 100.0
Facebook 40 100.0
Instagram 40 100.0
Youtube 40 100.0
Linkedin 33 82.5
Tiktok 17 42.5
Upvotes: 2
Reputation: 44
To display the percentage values on top of each bar in your stacked bar chart, you can use the bar_label function provided by matplotlib.
for container in ax.containers:
ax.bar_label(container, labels=[f'{h:.0f}%' if h > 0 else '' for h in container.datavalues], label_type='edge')
Complete code :
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.ticker as mtick
plt.figure(figsize=(18,11),dpi=100)
sns.set_theme (style="whitegrid", palette="tab20b")
x_ekseni= ['İlgili Sosyal Medya Hesapları']
Website= [40]
Twitter= [40]
Facebook= [40]
Instagram= [40]
Youtube= [40]
Linkedin= [33]
Tiktok= [17]
index=x_ekseni
df = pd.DataFrame({'Website': Website,
'Twitter': Twitter,
'Facebook': Facebook,
'Instagram': Instagram,
'Youtube': Youtube,
'Linkedin': Linkedin,
'Tiktok': Tiktok}, index=index)
ax = df.plot.bar(stacked=False, edgecolor='white', width=2.5, linewidth=0.5)
for container in ax.containers:
ax.bar_label(container, labels=[f'{h:.0f}%' if h > 0 else '' for h in container.datavalues], label_type='edge')
plt.title("İstanbul'daki Belediyelerin Sosyal Medya Kullanımı", fontsize=11, fontweight=0, color="black", loc="center")
ax.set_ylabel("İldeki Tüm Belediyeler İçinde Yüzde (n=40)", fontsize=10)
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
plt.xticks(rotation=0, fontsize=8)
plt.yticks(rotation=0, fontsize=8)
plt.ylim(0, 100)
ax.legend(frameon=True, fontsize=8)
plt.show()
Upvotes: 0