Python & Pandas:当 Pandas 将直方图绘制到特定轴时的奇怪行为

Posted

技术标签:

【中文标题】Python & Pandas:当 Pandas 将直方图绘制到特定轴时的奇怪行为【英文标题】:Python & Pandas: Strange behavior when Pandas plot histogram to a specific ax 【发布时间】:2016-11-15 12:03:02 【问题描述】:

我想将 pandas 直方图绘制到一个轴上,但这种行为真的很奇怪。我不知道这里出了什么问题。

fig1, ax1 = plt.subplots(figsize=(4,3))
fig2, ax2 = plt.subplots(figsize=(4,3))
fig3, ax3 = plt.subplots(figsize=(4,3))

# 1. This works
df['speed'].hist()

# 2. This doens't work
df['speed'].hist(ax=ax2)

# 3. This works
data = [1,2,3,5,6,2,3,4]
temp_df = pd.DataFrame(data)
temp_df.hist(ax=ax2)

jupyter notebook 返回的错误是:


AssertionError                            Traceback (most recent call last)
<ipython-input-46-d629de832772> in <module>()
      7 
      8 # This doens't work
----> 9 df['speed'].hist(ax=ax2)
     10 
     11 # # This works

D:\Anaconda2\lib\site-packages\pandas\tools\plotting.pyc in hist_series(self, by, ax, grid, xlabelsize, xrot, ylabelsize, yrot, figsize, bins, **kwds)
   2953             ax = fig.gca()
   2954         elif ax.get_figure() != fig:
-> 2955             raise AssertionError('passed axis not bound to passed figure')
   2956         values = self.dropna().values
   2957 

AssertionError: passed axis not bound to passed figure

熊猫源代码在这里:

https://github.com/pydata/pandas/blob/d38ee272f3060cb884f21f9f7d212efc5f7656a8/pandas/tools/plotting.py#L2913

完全不知道我的代码有什么问题。

【问题讨论】:

我在尝试将 Pandas.hist() 图显示到 PyQt5 Ui 时也遇到了同样的问题。真令人沮丧。建议的解决方案均无效。 【参考方案1】:

问题在于,pandas 通过使用gcf() 来获取“当前人物”来确定哪个是活动人物。当您连续创建多个图形时,“当前图形”是最后一个创建的图形。但是您正试图绘制到更早的一个,这会导致不匹配。

但是,正如您在链接到的源代码的第 2954 行所看到的,pandas 将寻找(未记录的)figure 参数。所以你可以通过df['speed'].hist(ax=ax2, figure=fig2) 让它工作。 pandas 源中的一条评论指出,这是“在绘图界面更加统一之前的修改”,所以我不会依赖它来做任何太重要的事情。

另一种解决方案是在您准备好使用之前不要创建新图。在上面的示例中,您只使用了图 2,因此无需创建其他示例。当然,这是一个人为的例子,但在现实生活中,如果你有这样的代码:

fig1, ax1 = plt.subplots(figsize=(4,3))
fig2, ax2 = plt.subplots(figsize=(4,3))
fig3, ax3 = plt.subplots(figsize=(4,3))

something.hist(ax=ax1)
something.hist(ax=ax2)
something.hist(ax=ax3)

你可以改成这样:

fig1, ax1 = plt.subplots(figsize=(4,3))
something.hist(ax=ax1)

fig2, ax2 = plt.subplots(figsize=(4,3))
something.hist(ax=ax2)

fig3, ax3 = plt.subplots(figsize=(4,3))
something.hist(ax=ax3)

也就是说,将绘图代码的每个部分放在为该绘图创建图形的代码之后。

【讨论】:

我也遇到了这个问题,但是我没看明白答案:pandas确定哪个是活动图第二种情况,大佬指ax=ax2但为什么还不够?如果您输入一个简单的plot,而不是hist,它就可以工作。为什么这两个功能有区别?谢谢 @SPS:为什么?我不知道。使用未记录的figure 参数的黑客似乎只存在于hist 中。为什么会这样,我不知道。 谢谢!!知道您可以将图形传递给熊猫图,我非常有用【参考方案2】:

在尝试将 Pandas 直方图绘制到 PyQt5 小部件(来自使用 Qt Creator 创建的 UI)中时,我遇到了类似的问题。

代码看起来像这样:

from PyQt5 import QtWidgets
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvas
import numpy as np
import pandas as pd


class MplWidget(QtWidgets.QWidget):

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)

        self.canvas = FigureCanvas(Figure())

        vertical_layout = QtWidgets.QVBoxLayout()
        vertical_layout.addWidget(self.canvas)

        self.canvas.axes = self.canvas.figure.add_subplot(111)
        self.setLayout(vertical_layout)

index1 = np.random.rand(10000)
data1 = np.random.gamma(2, 2, 10000)

s1 = pd.Series(data1, index=index1)

MplWidget_object = MplWidget_FROM_MY_GUI

s1.hist(ax=MplWidget_object.canvas.axes) # This would throw an error.
pd.DataFrame(s1).hist(ax=MplWidget_object.canvas.axes) # This Works!!!

我设法通过将我的 pandas.Series 转换为 Dataframe 来使其工作(两行代码)

【讨论】:

以上是关于Python & Pandas:当 Pandas 将直方图绘制到特定轴时的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

扁平化(不规则)Python 中关于 Pandas Dataframes 的列表列表

python & pandas学习札记

编辑 DataFrafe 列中的值-Python 和 PANDAS [重复]

Pandas初学者代码优化指南

python & pandas链接mysql数据库

python---pandas