【问题标题】:Inconsistency when setting figure size using pandas plot method使用 pandas 绘图方法设置图形大小时的不一致
【发布时间】:2017-07-02 02:23:13
【问题描述】:

我正在尝试使用 pandas 数据框的 plot 方法的便利性,同时调整生成的图形的大小。 (我将这些数字保存到文件中,并在 Jupyter 笔记本中内联显示它们)。我发现下面的方法大部分时间都是成功的,除非我在同一个图表上绘制两条线 - 然后图形回到默认大小。

我怀疑这可能是由于系列图和数据帧图之间的差异。

设置示例代码:

data = {
    'A': 90 + np.random.randn(366),
    'B': 85 + np.random.randn(366)
}

date_range = pd.date_range('2016-01-01', '2016-12-31')

index = pd.Index(date_range, name='Date')

df = pd.DataFrame(data=data, index=index)

控制 - 此代码产生预期结果(宽图):

fig = plt.figure(figsize=(10,4))

df['A'].plot()
plt.savefig("plot1.png")
plt.show()

结果:

绘制两条线 - 图形大小不是 (10,4)

fig = plt.figure(figsize=(10,4))

df[['A', 'B']].plot()
plt.savefig("plot2.png")
plt.show()

结果:

这样做的正确方法是什么,以便无论选择的系列数量如何,图形大小都是一致的?

【问题讨论】:

  • 我想我现在找到了一个很好的解决方案:df[['A', 'B']].plot(figsize=(10,4)) 但是,我仍然很好奇为什么上述方法会产生不一致的结果。
  • 您需要创建坐标轴和图形,然后将坐标轴传递给plot 方法:fig, ax = plt.subplots(figsize=(10,4)); df[['A', 'B']].plot(ax=ax)

标签: python pandas matplotlib plot


【解决方案1】:

这两种情况不同的原因有点隐藏在pandas.DataFrame.plot()的逻辑里面。正如在the documentation 中看到的那样,此方法允许传递大量参数,以便处理各种不同的情况。

在第一种情况下,您通过 fig = plt.figure(figsize=(10,4)) 创建一个 matplotlib 图形,然后绘制一个单列 DataFrame。现在 pandas 绘图函数的内部逻辑是检查 matplotlib 状态机中是否已经存在一个图形,如果是,则使用它的当前轴将列值绘制到它。这按预期工作。

但是在第二种情况下,数据由两列组成。有几种方法可以处理这样的图,包括使用具有共享或非共享轴的不同子图等。为了让 pandas 能够应用任何这些可能的要求,默认情况下它会创建一个新的图形可以添加要绘制的轴。除非您指定 figsize 参数,否则新图形不会知道现有图形及其大小,而是具有默认大小。

在 cmets 中,您说可能的解决方案是使用 df[['A', 'B']].plot(figsize=(10,4))。这是正确的,但是您需要省略初始图形的创建。否则它将产生 2 个数字,这可能是不希望的。在笔记本中这将是不可见的,但如果您将其作为通常的 python 脚本运行,最后带有plt.show(),将会打开两个图形窗口。

所以让 pandas 处理图形创建的解决方案是

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({"A":[2,3,1], "B":[1,2,2]})
df[['A', 'B']].plot(figsize=(10,4))

plt.show()

避免创建新图形的一种方法是将ax 参数提供给pandas.DataFrame.plot(ax=ax) 函数,其中ax 是外部创建的轴。该轴可以是您通过plt.gca() 获得的标准轴。

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({"A":[2,3,1], "B":[1,2,2]})
plt.figure(figsize=(10,4))
df[['A', 'B']].plot(ax = plt.gca())

plt.show()

或者使用answer from PaulH中看到的更面向对象的方式。

【讨论】:

    【解决方案2】:

    始终明确直接地对您的 FigureAxes 对象进行操作。不要依赖pyplot 状态机。在您的情况下,这意味着:

    fig1, ax1 = plt.subplots(figsize=(10,4))
    df['A'].plot(ax=ax1)
    fig1.savefig("plot1.png")
    
    
    fig2, ax2 = plt.figure(figsize=(10,4)) 
    df[['A', 'B']].plot(ax=ax2)
    fig2.savefig("plot2.png")
    
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-08
      • 1970-01-01
      • 2020-05-21
      • 1970-01-01
      • 2019-06-26
      • 2022-11-20
      • 1970-01-01
      相关资源
      最近更新 更多