在 Pandas/Matplotlib 上输入图例后命名堆积条

Posted

技术标签:

【中文标题】在 Pandas/Matplotlib 上输入图例后命名堆积条【英文标题】:Name stacked bars after legend entry on Pandas/Matplotlib 【发布时间】:2021-07-21 05:17:12 【问题描述】:

我有一个堆积条形图,非常适合我要查找的内容。我的问题是处理标签。

我可以在其值(数字)之后标记每个堆叠条,但我希望在其名称(在图例上)之后标记它。

有人知道如何解决这个问题吗?

ps.:很遗憾我还不能发布图片。

I have something like this:
    ####
    #15#
    ####
    oooo        ####
    oooo        #35#
    o55o        ####
    oooo        ####
    oooo        o12o


And need like this:
    ####
    #### A
    ####
    oooo        ####
    oooo B      #### A
    oooo        ####
    oooo        oooo B

【问题讨论】:

【参考方案1】:

我写了一个简短的例子,请看下面的代码:

import numpy as np
import matplotlib.pyplot as plt

# Some data
x  = np.array([0, 1, 2])
y1 = np.array([3, 4, 1])
y2 = np.array([2, 2, 4])

# label text
label_y1 = 'y1'
label_y2 = 'y2'

# Create the base plot
fig, ax = plt.subplots()

bars_y1 = ax.bar(x, y1, width=0.5, label=label_y1)
bars_y2 = ax.bar(x, y2, width=0.5, label=label_y2, bottom=y1)

# Function to add labels to the plot
def add_labels(ax, bars, label):
    for bar in bars:
        # Get the desired x and y locations
        xloc = bar.get_x() + 1.05 * bar.get_width()
        yloc = bar.get_y() + bar.get_height() / 2
        
        ax.annotate(label, xy=(xloc, yloc), va='center', ha='left', color=bar.get_facecolor())


# Add the labels in the plot
add_labels(ax, bars_y1, label_y1)
add_labels(ax, bars_y2, label_y2)

plt.show()

首先,我生成一些虚拟数据(xy1y2)。然后,我定义所需的标签文本(label_y1label_y2),最后我使用Axes.bar 制作基本条形图。请注意,我存储了来自 Axes.bar 调用的返回值,这是一个包含所有条形的容器!

现在,我们进入有趣的部分。我定义了一个名为add_labels 的函数。作为输入,它需要感兴趣的轴、一个包含所有条形的容器和所需的标签文本。在函数体中,我遍历所有条形并确定标签文本所需的 x 和 y 位置。使用这些值,我使用Axes.annotate 方法将标签文本放置在这些坐标处。在脚本结束时,我只需使用所需的参数调用 add_labels 函数即可获得以下输出:

这是你要找的吗?

【讨论】:

嗨,德克斯!非常感谢您的回答!我以不同的方式解决了它,但你的回答帮助我意识到我错过了什么!谢谢!!!我的问题有一些额外的要求,例如: - 数据框上的可变列数 - 行数 - 可用大小所以我使用图中的补丁来处理图例,如下所示【参考方案2】:

根据 Dex 的回答,我想出了一个解决方案。 使用补丁,它将从图表中获取每个条形图。条形按行排列。所以如果你有一个 4x3 的数据框:

   zero  um  dois
0     a   b     c
1     d   e     f
2     g   h     i
3     j   k     l

bars.patches 的每一列将依次排列:[a,d,g,j,b,e,h,k,c,f,i,l]

因此,每 4 个项目(行),它就会重新启动。为此,我们可以根据 df 上的行数使用 mod 函数 (%):

i % len(df.index)  == 0   #moves position counter to the next column name

代码最终是这样的:

import pandas as pd
import numpy as np

# Some data
x  = np.array(['zero', 'um', 'dois'])
y = np.array([[3, 4, 8],[2, 2, 4],[6, 7, 8]])

df = pd.DataFrame(y, columns = x)

print(df)

   zero  um  dois
0     3   4     8
1     2   2     4
2     6   7     8



title = 'Chart Title'
bars = df.plot.bar(ax = ax, stacked = True, title = title, legend = False)

plt.xlabel('x axis label')

pos = -1
for i, bar in enumerate(bars.patches):     #runs through every single bar on the chart
    if i % len(df.index) == 0:             #based on lenght of the index, gets which label 
        pos += 1                           #to use from the columns. Returning to the 
                                           #first after completing a row
        
    xloc = bar.get_x()                     
    yloc = bar.get_y() + bar.get_height() / 2
    if bar.get_height() > 30:
        ax.annotate(str(df.columns[pos]), xy = (xloc, yloc), va='center', ha='left')

                        #df.columns[pos] will get the correct column name


因此,无论数据框的大小如何,它都会在条形旁边绘制列名

图表示例: https://i.stack.imgur.com/2iHau.png

【讨论】:

以上是关于在 Pandas/Matplotlib 上输入图例后命名堆积条的主要内容,如果未能解决你的问题,请参考以下文章

Pandas Matplotlib:如何更改散点图中图例的形状和大小?

如何在 pandas/matplotlib 中绘制索引列?

如何在 pandas / matplotlib 中绘制多条线

解决Pandas/Matplotlib保存图形时坐标轴标签太长导致显示不全的问题

Python+pandas+matplotlib数据分析与可视化案例

在 pandas/matplotlib 中为图形标题拉取数据框名称