如何绘制百分比柱状图并用数值注释。

huangapple go评论105阅读模式
英文:

How to plot bars against percent and annotate with the value

问题

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).

我不想看到条形图的百分比,我想要数值(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.

我希望有7个高度为其百分比的条形图,但条形图上的容器应该带有它们的值名称。例如,在我的问题中,n=40;第一根条形图的值为40。因此,这些条形图的顶部应该在100%水平,但容器上必须写成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.

还有另一个例子;最后(Tiktok条形图)的条形图的值为17,所以容器应该显示17,但条形图的高度应为42.5%。

英文:

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

Sample DataFrame and Imports

  1. import pandas as pd
  2. import matplotlib.pyplot as plt
  3. import seaborn as sns
  4. import matplotlib.ticker as mtick
  5. plt.figure(figsize=(18,11),dpi=100)
  6. sns.set_theme (style="whitegrid", palette="tab20b")
  7. x_ekseni= [&#39lgili Sosyal Medya Hesapları']
  8. Website= [40]
  9. Twitter= [40]
  10. Facebook= [40]
  11. Instagram= [40]
  12. Youtube= [40]
  13. Linkedin= [33]
  14. Tiktok= [17]
  15. index=x_ekseni
  16. df = pd.DataFrame({'Website': Website,
  17. 'Twitter': Twitter,
  18. 'Facebook': Facebook,
  19. 'Instagram': Instagram,
  20. 'Youtube': Youtube,
  21. 'Linkedin': Linkedin,
  22. 'Tiktok': Tiktok}, index=index)

df

  1. Website Twitter Facebook Instagram Youtube Linkedin Tiktok
  2. İlgili Sosyal Medya Hesapları 40 40 40 40 40 33 17

Plot

  1. ax = df.plot.bar(stacked=False,edgecolor='white',width = 2.5,linewidth=0.5)
  2. # iterate through the containers
  3. for c in ax.containers:
  4. # get the current segment label (a string); corresponds to column / legend
  5. col = c.get_label()
  6. labels = df[col].replace(0, '')
  7. # add the annotation
  8. ax.bar_label(c, labels=labels, label_type='center', fontweight='bold', color='white',fontsize=10)
  9. plt.title(&quotstanbul'daki Belediyelerin Sosyal Medya Kullanımı", fontsize=11, fontweight=0, color="black", loc="center")
  10. ax.set_ylabel(&quotldeki Tüm Belediyeler İçinde Yüzde (n=40)", fontsize= 10)
  11. ax.yaxis.set_major_formatter(mtick.PercentFormatter())
  12. plt.xticks(rotation=0,fontsize=8)
  13. plt.yticks(rotation=0,fontsize=8)
  14. plt.ylim(0,100)
  15. ax.legend(frameon=True, fontsize=8)

如何绘制百分比柱状图并用数值注释。

答案1

得分: 2

  • python 3.11.2, pandas 2.0.0, matplotlib 3.7.1, seaborn 0.12.2 中测试通过
  • 请注意,OP 中的图表是单个柱形组,这就是为什么只有一个刻度的原因。
  • 为了使柱形的高度与其相应的百分比值相等,请计算并添加一个新列,该列包含百分比值,然后使用新列绘制柱形,并将实际值传递给 .bar_label 中的 labels= 参数。

导入和 DataFrame

  1. import pandas as pd
  2. import matplotlib.ticker as tkr
  3. import matplotlib.pyplot as plt
  4. import seaborn as sns
  5. # 测试数据框
  6. data = {'网站': [40], 'Twitter': [40], 'Facebook': [40], 'Instagram': [40], 'Youtube': [40], 'Linkedin': [33], 'Tiktok': [17]}
  7. df = pd.DataFrame(data, index=['相关社交媒体帐户'])
  8. # 将数据框从宽格式转换为长格式
  9. df = df.T
  10. # 添加百分比列
  11. df['百分比'] = df.div(df.sum()).mul(100).round(2)

df

  1. 相关社交媒体帐户 百分比
  2. 网站 40 16.0
  3. Twitter 40 16.0
  4. Facebook 40 16.0
  5. Instagram 40 16.0
  6. Youtube 40 16.0
  7. Linkedin 33 13.2
  8. Tiktok 17 6.8

使用 pandas.DataFrame.plotkind='bar' 绘制图表

  1. # 绘制百分比列
  2. ax = df.plot(kind='bar', y='百分比', rot=0, figsize=(10, 7), ylabel='', legend=False)
  3. # 添加标注;只有一个包含 7 个艺术家的容器
  4. # 只需要在容器之间进行迭代,以便在分组或堆叠柱形图中有多个容器时才需要
  5. ax.bar_label(ax.containers[0], labels=df['相关社交媒体帐户'].replace(0, ''), label_type='center', fontweight='bold', color='white', fontsize=10)
  6. ax.set_title("伊斯坦布尔市政府的社交媒体使用", fontsize=11, fontweight=0, color="black", loc="center")
  7. ax.set_ylabel("在市内所有市政府中的百分比 (n=40)", fontsize= 10)
  8. ax.set_xlabel(df.columns[0], fontsize= 10)
  9. ax.yaxis.set_major_formatter(tkr.PercentFormatter())
  10. ax.tick_params(axis='both', which='major', labelsize=8)
  11. _ = ax.set_ylim(0, 100)

如何绘制百分比柱状图并用数值注释。

使用 seaborn.barplot 绘制图表

  1. plt.figure(figsize=(10, 7))
  2. # 绘制 df,但索引必须重置
  3. ax = sns.barplot(data=df.reset_index(), x='index', y='百分比')
  4. ax.bar_label(ax.containers[0], labels=df['相关社交媒体帐户'].replace(0, ''), label_type='center', fontweight='bold', color='white', fontsize=10)
  5. ax.set_title("伊斯坦布尔市政府的社交媒体使用", fontsize=11, fontweight=0, color="black", loc="center")
  6. ax.set_ylabel("在市内所有市政府中的百分比 (n=40)", fontsize= 10)
  7. ax.set_xlabel(df.columns[0], fontsize= 10)
  8. ax.yaxis.set_major_formatter(tkr.PercentFormatter())
  9. ax.tick_params(axis='both', which='major', labelsize=8)
  10. _ = ax.set_ylim(0, 100)

如何绘制百分比柱状图并用数值注释。

注意

  • 根据 OP 中从评论中添加的附加信息更新,其中百分比根据特定值 n=40 计算,请使用以下方法计算 百分比 列。
  • 先前代码中的其他内容无需更改。
  1. # 一个任意值
  2. n = 40
  3. df['百分比'] = df.div(n, axis=0).mul(100).round(2)
  4. # 或
  5. # 列中的最大值
  6. df['百分比'] = df.div(df.iloc[:, 0].max(), axis=0).mul(100).round(2)
  1. 相关社交媒体帐户 百分比
  2. 网站 40 100.0
  3. Twitter 40 100.0
  4. Facebook 40 100.0
  5. Instagram 40 100.0
  6. Youtube 40 100.0
  7. Linkedin 33 82.5
  8. Tiktok 17 42.5

[![使用 pandas.DataFrame.plot 绘制的图表][6]][6]

[![使用 seaborn.barplot 绘制的图表][7]][7]

英文:
  • Tested in python 3.11.2, pandas 2.0.0, matplotlib 3.7.1, seaborn 0.12.2
  • Note the plot in the OP is a single group of bars, which is why there's only one tick.
  • In order to have the bars be the height of their respective percent value, calculate and add a new column with the percent value, plot the bars with the new column, and pass the actual values to the labels= parameter in .bar_label.

Imports and DataFrame

  1. import pandas as pd
  2. import matplotlib.ticker as tkr
  3. import matplotlib.pyplot as plt
  4. import seaborn as sns
  5. # test dataframe
  6. data = {'Website': [40], 'Twitter': [40], 'Facebook': [40], 'Instagram': [40], 'Youtube': [40], 'Linkedin': [33], 'Tiktok': [17]}
  7. df = pd.DataFrame(data, index=[&#39lgili Sosyal Medya Hesapları'])
  8. # transpose df from a wide to a long form
  9. df = df.T
  10. # add a percent column
  11. df['per'] = df.div(df.sum()).mul(100).round(2)

df

  1. İlgili Sosyal Medya Hesapları per
  2. Website 40 16.0
  3. Twitter 40 16.0
  4. Facebook 40 16.0
  5. Instagram 40 16.0
  6. Youtube 40 16.0
  7. Linkedin 33 13.2
  8. Tiktok 17 6.8

Plot using pandas.DataFrame.plot with kind='bar'

  1. # plot percent column
  2. ax = df.plot(kind='bar', y='per', rot=0, figsize=(10, 7), ylabel='', legend=False)
  3. # add the annotations; there's only 1 container of 7 artists
  4. # iterating through the containers is only necessary for grouped or stacked bars, which have multiple containers
  5. ax.bar_label(ax.containers[0], labels=df[&#39lgili Sosyal Medya Hesapları'].replace(0, ''), label_type='center', fontweight='bold', color='white', fontsize=10)
  6. ax.set_title(&quotstanbul'daki Belediyelerin Sosyal Medya Kullanımı", fontsize=11, fontweight=0, color="black", loc="center")
  7. ax.set_ylabel(&quotldeki Tüm Belediyeler İçinde Yüzde (n=40)", fontsize= 10)
  8. ax.set_xlabel(df.columns[0], fontsize= 10)
  9. ax.yaxis.set_major_formatter(tkr.PercentFormatter())
  10. ax.tick_params(axis='both', which='major', labelsize=8)
  11. _ = ax.set_ylim(0, 100)

如何绘制百分比柱状图并用数值注释。

Plot using seaborn.barplot

  1. plt.figure(figsize=(10, 7))
  2. # plot df, but the index must be reset
  3. ax = sns.barplot(data=df.reset_index(), x='index', y='per')
  4. ax.bar_label(ax.containers[0], labels=df[&#39lgili Sosyal Medya Hesapları'].replace(0, ''), label_type='center', fontweight='bold', color='white', fontsize=10)
  5. ax.set_title(&quotstanbul'daki Belediyelerin Sosyal Medya Kullanımı", fontsize=11, fontweight=0, color="black", loc="center")
  6. ax.set_ylabel(&quotldeki Tüm Belediyeler İçinde Yüzde (n=40)", fontsize= 10)
  7. ax.set_xlabel(df.columns[0], fontsize= 10)
  8. ax.yaxis.set_major_formatter(tkr.PercentFormatter())
  9. ax.tick_params(axis='both', which='major', labelsize=8)
  10. _ = ax.set_ylim(0, 100)

如何绘制百分比柱状图并用数值注释。

Note

  • Updated based on additional information added to the OP from a comment, where the percent is calculated against a specific value, n=40, use the following to calculate the 'per' column.
  • Nothing else in the previous code needs to change.
  1. # an arbitrary value
  2. n = 40
  3. df['per'] = df.div(n, axis=0).mul(100).round(2)
  4. # or
  5. # the max value in the column
  6. df['per'] = df.div(df.iloc[:, 0].max(), axis=0).mul(100).round(2)
  1. İlgili Sosyal Medya Hesapları per
  2. Website 40 100.0
  3. Twitter 40 100.0
  4. Facebook 40 100.0
  5. Instagram 40 100.0
  6. Youtube 40 100.0
  7. Linkedin 33 82.5
  8. Tiktok 17 42.5

[![plotted with pandas.DataFrame.plot][6]][6]

[![plotted with seaborn.barplot][7]][7]

[6]: https://i.stack.imgur.com/zl0df.png "plotted with pandas.DataFrame.plot"
[7]: https://i.stack.imgur.com/goajF.png "plotted with seaborn.barplot"

答案2

得分: 0

  1. 为了在堆叠条形图的每个条形上方显示百分比数值您可以使用matplotlib提供的bar_label函数
  2. ```python
  3. for container in ax.containers:
  4. ax.bar_label(container, labels=[f'{h:.0f}%' if h > 0 else '' for h in container.datavalues], label_type='edge')

完整代码:

  1. import pandas as pd
  2. import matplotlib.pyplot as plt
  3. import seaborn as sns
  4. import matplotlib.ticker as mtick
  5. plt.figure(figsize=(18, 11), dpi=100)
  6. sns.set_theme(style="whitegrid", palette="tab20b")
  7. x_ekseni = ['相关社交媒体账户']
  8. Website = [40]
  9. Twitter = [40]
  10. Facebook = [40]
  11. Instagram = [40]
  12. Youtube = [40]
  13. Linkedin = [33]
  14. Tiktok = [17]
  15. index = x_ekseni
  16. df = pd.DataFrame({'Website': Website,
  17. 'Twitter': Twitter,
  18. 'Facebook': Facebook,
  19. 'Instagram': Instagram,
  20. 'Youtube': Youtube,
  21. 'Linkedin': Linkedin,
  22. 'Tiktok': Tiktok}, index=index)
  23. ax = df.plot.bar(stacked=False, edgecolor='white', width=2.5, linewidth=0.5)
  24. for container in ax.containers:
  25. ax.bar_label(container, labels=[f'{h:.0f}%' if h > 0 else '' for h in container.datavalues], label_type='edge')
  26. plt.title("伊斯坦布尔市政府的社交媒体使用", fontsize=11, fontweight=0, color="black", loc="center")
  27. ax.set_ylabel("在市内所有市政府中的百分比(n=40)", fontsize=10)
  28. ax.yaxis.set_major_formatter(mtick.PercentFormatter())
  29. plt.xticks(rotation=0, fontsize=8)
  30. plt.yticks(rotation=0, fontsize=8)
  31. plt.ylim(0, 100)
  32. ax.legend(frameon=True, fontsize=8)
  33. plt.show()
英文:

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.

  1. for container in ax.containers:
  2. ax.bar_label(container, labels=[f'{h:.0f}%' if h > 0 else '' for h in container.datavalues], label_type='edge')

Complete code :

  1. import pandas as pd
  2. import matplotlib.pyplot as plt
  3. import seaborn as sns
  4. import matplotlib.ticker as mtick
  5. plt.figure(figsize=(18,11),dpi=100)
  6. sns.set_theme (style="whitegrid", palette="tab20b")
  7. x_ekseni= [&#39lgili Sosyal Medya Hesapları']
  8. Website= [40]
  9. Twitter= [40]
  10. Facebook= [40]
  11. Instagram= [40]
  12. Youtube= [40]
  13. Linkedin= [33]
  14. Tiktok= [17]
  15. index=x_ekseni
  16. df = pd.DataFrame({'Website': Website,
  17. 'Twitter': Twitter,
  18. 'Facebook': Facebook,
  19. 'Instagram': Instagram,
  20. 'Youtube': Youtube,
  21. 'Linkedin': Linkedin,
  22. 'Tiktok': Tiktok}, index=index)
  23. ax = df.plot.bar(stacked=False, edgecolor='white', width=2.5, linewidth=0.5)
  24. for container in ax.containers:
  25. ax.bar_label(container, labels=[f'{h:.0f}%' if h > 0 else '' for h in container.datavalues], label_type='edge')
  26. plt.title(&quotstanbul'daki Belediyelerin Sosyal Medya Kullanımı", fontsize=11, fontweight=0, color="black", loc="center")
  27. ax.set_ylabel(&quotldeki Tüm Belediyeler İçinde Yüzde (n=40)", fontsize=10)
  28. ax.yaxis.set_major_formatter(mtick.PercentFormatter())
  29. plt.xticks(rotation=0, fontsize=8)
  30. plt.yticks(rotation=0, fontsize=8)
  31. plt.ylim(0, 100)
  32. ax.legend(frameon=True, fontsize=8)
  33. plt.show()

huangapple
  • 本文由 发表于 2023年4月17日 17:19:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76033552.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定