【问题标题】:Annotating Pandas Barplot with an Additional Value Unrelated to the Plot's x and y Axis使用与绘图的 x 和 y 轴无关的附加值注释 Pandas Barplot
【发布时间】:2021-04-28 16:52:38
【问题描述】:

我正在制作一个 pandas 条形图,其原始计数由该图表示,但是我想用这些计数的 pct 作为一个整体来注释条形图。我见过很多人使用ax.patches 方法进行注释,但我的值与实际条形的get_height 无关。

这是一些玩具数据。生成的图将是特定类型的单个计数。但是,我想在该特定栏上方添加注释,表示该特定类型的 pct 总数到该人姓名的所有类型。

如果您需要更多说明,请告诉我。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt


d = {'ID': [1,1,1,2,2,3,3,3,4], 
     'name': ['bob','bob','bob','shelby','shelby','jordan','jordan','jordan','jeff'],
     'type': ['type1','type2','type4','type1','type6','type5','type8','type2',None]}
df: pd.DataFrame = pd.DataFrame(data=d)

df_pivot: pd.DataFrame = df.pivot_table(index='type', columns=['name'], values='ID', aggfunc={'ID': np.sum}).fillna(0)

# create percent totals of the specific type's row of the total
df_pivot['bob_pct_total']: pd.Series = (df_pivot['bob']/df_pivot['bob'].sum()).mul(100).round(1)
df_pivot['shelby_pct_total']: pd.Series = (df_pivot['shelby']/df_pivot['shelby'].sum()).mul(100).round(1)
df_pivot['jordan_pct_total']: pd.Series = (df_pivot['jordan']/df_pivot['jordan'].sum()).mul(100).round(1)
df_pivot.head(10)

name    bob jordan  shelby  bob_pct_total   shelby_pct_total    jordan_pct_total
type                        
type1   1.0   0.0      2.0           33.3               50.0                0.0
type2   1.0   3.0      0.0           33.3                0.0               33.3
type4   1.0   0.0      0.0           33.3                0.0                0.0
type5   0.0   3.0      0.0            0.0                0.0               33.3
type6   0.0   0.0      2.0            0.0               50.0                0.0
type8   0.0   3.0      0.0            0.0                0.0               33.3

fig, ax = plt.subplots(figsize=(15,15))
df_pivot.plot(kind='bar', y=['bob','jordan','shelby'], ax=ax)

【问题讨论】:

  • 您可以使用get_height() 计算位置,然后在此处写入另一个字符串。

标签: python pandas dataframe matplotlib


【解决方案1】:

您可以使用旧方法,遍历条形,使用高度来定位您想要的任何文本。从 matplotlib 3.4.0 开始,还有一个新函数 bar_label 删除了大部分样板:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

d = {'ID': [1, 1, 1, 2, 2, 3, 3, 3, 4],
     'name': ['bob', 'bob', 'bob', 'shelby', 'shelby', 'jordan', 'jordan', 'jordan', 'jeff'],
     'type': ['type1', 'type2', 'type4', 'type1', 'type6', 'type5', 'type8', 'type2', None]}
df: pd.DataFrame = pd.DataFrame(data=d)

df_pivot: pd.DataFrame = df.pivot_table(index='type', columns=['name'], values='ID', aggfunc={'ID': np.sum}).fillna(0)

# create percent totals of the specific type's row of the total
df_pivot['bob_pct_total']: pd.Series = (df_pivot['bob'] / df_pivot['bob'].sum()).mul(100).round(1)
df_pivot['shelby_pct_total']: pd.Series = (df_pivot['shelby'] / df_pivot['shelby'].sum()).mul(100).round(1)
df_pivot['jordan_pct_total']: pd.Series = (df_pivot['jordan'] / df_pivot['jordan'].sum()).mul(100).round(1)

fig, ax = plt.subplots(figsize=(12, 5))
columns = ['bob', 'jordan', 'shelby']
df_pivot.plot(kind='bar', y=['bob', 'jordan', 'shelby'], rot=0, ax=ax)
for bars, col in zip(ax.containers, ['bob_pct_total', 'jordan_pct_total', 'shelby_pct_total']):
    ax.bar_label(bars, labels=['' if val == 0 else f'{val}' for val in df_pivot[col]])
plt.tight_layout()
plt.show()

PS:要跳过标记第一条,您可以尝试:

for bars, col in zip(ax.containers, ['bob_pct_total', 'jordan_pct_total', 'shelby_pct_total']):
    labels=['' if val == 0 else f'{val}' for val in df_pivot[col]]
    labels[0] = ''
    ax.bar_label(bars, labels=labels)

【讨论】:

  • 这真是太好了。我使用的是旧版本的 Matplotlib。刚刚更新,这真的很有帮助。我总是发现 Matplotlib 中的注释非常麻烦和令人沮丧,但这是完美的!
  • 这可能有点小众,但如果我想省略酒吧组的注释之一,我该怎么做?由于容器包含 6 个艺术家,我需要为每个容器省略第一个艺术家。所以基本上如果我想隐藏“type1”注释,我该如何继续?我想我可以手动将这些 val 设置为 0,这样当它绘制时它只会使它们变为空白。
  • 是的,将这个值设置为零可能是最简单的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-18
  • 2012-06-08
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 2018-04-08
相关资源
最近更新 更多