【问题标题】:MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instanceMatplotlibDeprecationWarning:使用与先前轴相同的参数添加轴当前重用早期实例
【发布时间】:2019-05-08 07:40:00
【问题描述】:

我正在编写一个脚本,该脚本根据节点的数量接收多个输入、解析数据并多次调用绘图函数。

问题是我多次调用我的绘图函数(见下面的代码),但我不知道如何解决这个问题。我看到了this solution,但这不是我的情况(或者我不知道如何申请我的情况)。

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

sns.set(style="whitegrid")
fig, (ax1, ax2, ax3, ax4) = plt.subplots(nrows=1, ncols=4, figsize=(16, 4))
plt.tight_layout()


def plot_data(df, nodes):
  global ax1, ax2, ax3, ax4
  if nodes == 10:
    plt.subplot(141)
    ax1 = sns.kdeplot(df['Metric'], cumulative=True, legend=False)
    ax1.set_ylabel('ECDF', fontsize = 16)
    ax1.set_title('10 Nodes')

  elif nodes == 20:
    plt.subplot(142)
    ax2 = sns.kdeplot(df['Metric'], cumulative=True, legend=False)
    plt.setp(ax2.get_yticklabels(), visible=False)
    ax2.set_title('20 Nodes')

  elif nodes == 30:
    plt.subplot(143)
    ax3 = sns.kdeplot(df['Metric'], cumulative=True, legend=False)
    plt.setp(ax3.get_yticklabels(), visible=False)
    ax3.set_title('30 Nodes')

  elif nodes == 40:
    plt.subplot(144)
    ax4 = sns.kdeplot(df['Metric'], cumulative=True, legend=False)
    plt.setp(ax4.get_yticklabels(), visible=False)
    ax4.set_title('40 Nodes')


df1 = pd.DataFrame({'Metric':np.random.randint(0, 15, 1000)})    
df2 = pd.DataFrame({'Metric':np.random.randint(0, 15, 1000)})    
df3 = pd.DataFrame({'Metric':np.random.randint(0, 15, 1000)})    

nodes = [10, 20, 30, 40]
for i in range(4):
  """
  In my real code, the DataFrames are calculated from reading CSV files.
  Since that code would be too long, I'm using dummy data. 
  """
  plot_data(df1, nodes[i])
  # I understand that this calls cause the warning, 
  # but I don't know how to solve it
  plot_data(df2, nodes[i])
  plot_data(df3, nodes[i])
plt.show()  

【问题讨论】:

  • 我真的不明白你为什么要使用多个 ifs 而不是 if elif 以及为什么你没有将 axarr 对象从 subplots 传递到函数中(使用节点列表)并在函数中执行循环而不是调用函数 3 次?

标签: python matplotlib


【解决方案1】:

我认为这应该可以满足您的需要 - 只是将轴作为参数传递,然后将循环放入函数中

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

sns.set(style="whitegrid")
fig, axarr = plt.subplots(nrows=1, ncols=4, figsize=(16, 4))
plt.tight_layout()

nodes = [10, 20, 30, 40]

def plot_data(list_of_dfs, axarr, nodes):

    for df, ax, node in zip(list_of_dfs, axarr, nodes):
        ax = sns.kdeplot(df['Metric'], cumulative=True, legend=False)#I'm not completely sure this needs to be assignment, haven't used seaborn much
        ax.set_ylabel('ECDF', fontsize = 16)
        ax.set_title('{} Nodes'.format(nodes))

list_of_dfs = [df1, df2, df3]
plot_data(list_of_dfs, axarr, nodes)
plt.show()  

【讨论】:

    【解决方案2】:

    您需要删除plt.subplot(nnn)。正如警告所说,目前这样做将重用轴实例。但在未来的 matplotlib 版本中,这将创建一个新的轴实例。

    解决方案是将您创建的轴作为参数传递给函数,并使用seaborn.kdeplotax= 参数:

    sns.set(style="whitegrid")
    fig, axes = plt.subplots(nrows=1, ncols=4, figsize=(16, 4))
    plt.tight_layout()
    
    def plot_data(df, nodes, axes):
        ax1, ax2, ax3, ax4 = axes
        if nodes == 10:
            sns.kdeplot(df['Metric'], cumulative=True, legend=False, ax=ax1)
            ax1.set_ylabel('ECDF', fontsize = 16)
            ax1.set_title('10 Nodes')
        elif nodes == 20:
            sns.kdeplot(df['Metric'], cumulative=True, legend=False, ax=ax2)
            plt.setp(ax2.get_yticklabels(), visible=False)
            ax2.set_title('20 Nodes')
        elif nodes == 30:
            sns.kdeplot(df['Metric'], cumulative=True, legend=False, ax=ax3)
            plt.setp(ax3.get_yticklabels(), visible=False)
            ax3.set_title('30 Nodes')
        else:
            sns.kdeplot(df['Metric'], cumulative=True, legend=False, ax=ax4)
            plt.setp(ax4.get_yticklabels(), visible=False)
            ax4.set_title('40 Nodes')
    
    for i in range(4):
        plot_data(df1, nodes[i], axes)
        plot_data(df2, nodes[i], axes)
        plot_data(df3, nodes[i], axes)
    plt.show()
    

    请注意,您可以通过在 fig, axes = plt.subplots(…, sharey=True) 中使用 sharey=True 并删除 plt.setp(ax.get_yticklabels(), visible=False) 来简化上述操作

    【讨论】:

    • 请注意,出现警告是因为pyplot.subplot 当前使用与.add_subplot 相同的代码路径。该警告仅适用于后者,因为在 pyplot 中,在创建后激活子图当然很有用。所以我想这里的解决方案仍然是推荐的方法,但是使用 pyplot.subplot 也是同样可能的。
    猜你喜欢
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-06
    • 1970-01-01
    相关资源
    最近更新 更多