Python 为什么pyplot.plot()会创建一个宽度为1、高度为1的附加矩形?

Python 为什么pyplot.plot()会创建一个宽度为1、高度为1的附加矩形?,python,pandas,matplotlib,plot,Python,Pandas,Matplotlib,Plot,我正在从数据帧创建一个简单的条形图。(Series和DataFrame上的plot方法只是pyplot.plot的简单包装器) 这是生成的绘图 现在我想进入各个酒吧。我注意到有一个额外的条(矩形),宽度=1,高度=1 rects = [rect for rect in ax.get_children() if isinstance(rect, mpl.patches.Rectangle)] for r in rects: print(r) 输出: Rectangle(xy=(-0.25

我正在从数据帧创建一个简单的条形图。(Series和DataFrame上的plot方法只是pyplot.plot的简单包装器)

这是生成的绘图

现在我想进入各个酒吧。我注意到有一个额外的条(矩形),宽度=1,高度=1

rects = [rect for rect in ax.get_children() if isinstance(rect, mpl.patches.Rectangle)]
for r in rects:
   print(r)
输出:

Rectangle(xy=(-0.25, 0), width=0.5, height=3.42635e+06, angle=0)
Rectangle(xy=(0.75, 0), width=0.5, height=1.26039e+06, angle=0)
Rectangle(xy=(1.75, 0), width=0.5, height=1.73912e+06, angle=0)
Rectangle(xy=(0, 0), width=1, height=1, angle=0)

我希望这里只有三个矩形。第四个矩形的用途是什么?

第四个矩形是轴子地块的边界框。
这是Pyplot处理边界框的方式的产物,它不是熊猫特有的。例如,使用常规Pyplot打印:

f, ax = plt.subplots()
ax.bar(range(3), df.Population.values)
rects = [rect for rect in ax.get_children() if isinstance(rect, mpl.patches.Rectangle)]
for r in rects:
    print(r)
仍然会生成四个矩形:

Rectangle(-0.4,0;0.8x3.42635e+06)
Rectangle(0.6,0;0.8x1.26039e+06)
Rectangle(1.6,0;0.8x1.73912e+06)
Rectangle(0,0;1x1)
中有一行表示这个额外的矩形(以及为什么它的坐标是
(0,0)、(1,1)

…它指定子地块将装入的边界框。坐标必须为标准化地物坐标,默认值为(0,0,1,1)


Matplotlib文档中可能有一个更为正式的部分更详细地描述了这种体系结构,但我发现这些文档很难导航,这是我能想到的最好的方法。

您不想为了获得感兴趣的子对象而弄乱轴的所有子对象。如果轴中只有条形图,
>ax.patches
提供了轴中的矩形

关于条形图的标签,链接文章可能不是最佳选择。它主张手动计算标签的距离,这并不是真正有用的。相反,您只需使用参数
textcoords=“offset points”将注释与条形图顶部相比偏移一些点即可
plt.annotation

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({'City': ['Berlin', 'Munich', 'Hamburg'],
               'Population': [3426354, 1260391, 1739117]})
df = df.set_index('City')

ax = df.plot(kind='bar')


def autolabel(rects, ax):
    for rect in rects:
        x = rect.get_x() + rect.get_width()/2.
        y = rect.get_height()
        ax.annotate("{}".format(y), (x,y), xytext=(0,5), textcoords="offset points",
                    ha='center', va='bottom')

autolabel(ax.patches,ax)

ax.margins(y=0.1)
plt.show()

最后请注意,使用绘图中的形状来创建注释可能仍然不是最佳选择。为什么不使用数据本身呢

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({'City': ['Berlin', 'Munich', 'Hamburg'],
               'Population': [3426354, 1260391, 1739117]})

ax = df.plot(x = "City", y="Population", kind='bar')

def autolabel(s, ax=None, name=""):
    x = s.name
    y = s[name]
    ax.annotate("{}".format(y), (x,y), xytext=(0,5), textcoords="offset points",
                ha='center', va='bottom')

df.apply(autolabel, axis=1, ax=ax, name="Population")

ax.margins(y=0.1)
plt.show()

这将生成与上面相同的绘图。

感谢您的澄清。因此,我想如果我想访问绘图的条形图,我必须手动删除边框矩形。背景:我想使用这里描述的函数,您可以在
高度>1:
之后忽略它_高度()在链接到的
autolabel()
函数中。您还需要从这个答案中查找更多信息吗?不,只需先找到接受答案按钮=)谢谢
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({'City': ['Berlin', 'Munich', 'Hamburg'],
               'Population': [3426354, 1260391, 1739117]})

ax = df.plot(x = "City", y="Population", kind='bar')

def autolabel(s, ax=None, name=""):
    x = s.name
    y = s[name]
    ax.annotate("{}".format(y), (x,y), xytext=(0,5), textcoords="offset points",
                ha='center', va='bottom')

df.apply(autolabel, axis=1, ax=ax, name="Population")

ax.margins(y=0.1)
plt.show()