在同一个图 Python 中绘制从循环中获得的两个数据帧

Alb*_*ert 5 python plot matplotlib dataframe pandas

我想dfs用两种不同的颜色绘制两个。对于每个df,我需要添加两个标记。这是我尝试过的:

for stats_file in stats_files:
    data = Graph(stats_file)
    Graph.compute(data)
    data.servers_df.plot(x="time", y="percentage", linewidth=1, kind='line')
    plt.plot(data.first_measurement['time'], data.first_measurement['percentage'], 'o-', color='orange')
    plt.plot(data.second_measurement['time'], data.second_measurement['percentage'], 'o-', color='green')
plt.show()
Run Code Online (Sandbox Code Playgroud)

使用这段代码,我得到了servers_df带有标记的绘图,但在单独的图形上。我如何才能将两个图表放在一个图表中以更好地比较它们?

谢谢。

BSt*_*uer 5

长话短说

您的调用data.servers_df.plot()始终会创建一个新绘图,并plt.plot()在创建的最新绘图上绘图。解决方案是为要绘制的所有内容创建专用轴。

前言

我假设你的变量如下

  • data.servers_df:具有两个浮动列的数据框"time""percentage"
  • data.first_measurements:带有键和“百分比”的字典"time",每个键都是浮点数列表
  • data.second_measurements"time":带有键和 的字典"percentage",每个键都是浮点数列表

我跳过了生成stat_files,因为您没有显示Graph()做什么,而只是创建了一个虚拟列表data

如果data.first_measurementsdata.second_measurements也是数据框,请告诉我,有一个更好的解决方案。

理论——幕后

每个matplotlib图(线、条等)都存在于一个matplotlib.axes.Axes元素上。它们就像坐标系的规则轴。现在这里发生了两件事:

  • 当您使用 时plt.plot(),没有指定坐标区,因此,matplotlib 会查找当前坐标区元素(在后台),如果没有,它将创建一个空坐标区并使用它,并且设置为默认值。然后第二次调用plt.plot()找到这些轴并使用它们。
  • DataFrame.plot()另一方面,如果没有给它赋予任何元素,则总是创建一个新的轴元素(可以通过参数ax

因此,在您的代码中,data.servers_df.plot()首先在窗帘后面创建一个轴元素(这是默认的),然后以下两个plt.plot()调用获取默认轴并在其上绘图 - 这就是为什么您会得到两个图而不是一个图。

解决方案

以下解决方案首先创建一个专用的matplotlib.axes.Axesusing plt.subplots(). 然后使用该轴元素绘制所有线条。特别注意ax=ax中的data.server_df.plot(). 请注意,我将标记的显示从 更改o-o(因为我们不想显示线条 ( -),而只显示标记 ( o))。模拟数据可以在下面找到

fig, ax = plt.subplots()  # Here we create the axes that all data will plot onto
for i, data in enumerate(stat_files):
    y_column = f'percentage_{i}'  # Make the columns identifiable
    data.servers_df \
        .rename(columns={'percentage': y_column}) \
        .plot(x='time', y=y_column, linewidth=1, kind='line', ax=ax)
    ax.plot(data.first_measurement['time'], data.first_measurement['percentage'], 'o', color='orange')
    ax.plot(data.second_measurement['time'], data.second_measurement['percentage'], 'o', color='green')
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

模拟数据

import random

import pandas as pd
import matplotlib.pyplot as plt

# Generation of dummy data
random.seed(1)
NUMBER_OF_DATA_FILES = 2
X_LENGTH = 10


class Data:
    def __init__(self):
        self.servers_df = pd.DataFrame(
            {
                'time': range(X_LENGTH),
                'percentage': [random.randint(0, 10) for _ in range(X_LENGTH)]
            }
        )
        self.first_measurement = {
            'time': self.servers_df['time'].values[:X_LENGTH // 2],
            'percentage': self.servers_df['percentage'].values[:X_LENGTH // 2]
        }
        self.second_measurement = {
            'time': self.servers_df['time'].values[X_LENGTH // 2:],
            'percentage': self.servers_df['percentage'].values[X_LENGTH // 2:]
        }


stat_files = [Data() for _ in range(NUMBER_OF_DATA_FILES)]
Run Code Online (Sandbox Code Playgroud)


Dji*_*011 3

DataFrame.plot()默认返回一个matplotlib.axes.Axes对象。然后您应该在该对象上绘制其他两个图:

for stats_file in stats_files:
    data = Graph(stats_file)
    Graph.compute(data)
    ax = data.servers_df.plot(x="time", y="percentage", linewidth=1, kind='line')
    ax.plot(data.first_measurement['time'], data.first_measurement['percentage'], 'o-', color='orange')
    ax.plot(data.second_measurement['time'], data.second_measurement['percentage'], 'o-', color='green')
plt.show()
Run Code Online (Sandbox Code Playgroud)

如果你想用不同的颜色将它们绘制在其他之上,你可以这样做:

colors = ['C0', 'C1', 'C2']  # matplotlib default color palette
                             # assuming that len(stats_files) = 3
                             # if not you need to specify as many colors as necessary 

ax = plt.subplot(111)
for stats_file, c in zip(stats_files, colors):
    data = Graph(stats_file)
    Graph.compute(data)
    data.servers_df.plot(x="time", y="percentage", linewidth=1, kind='line', ax=ax)
    ax.plot(data.first_measurement['time'], data.first_measurement['percentage'], 'o-', color=c)
    ax.plot(data.second_measurement['time'], data.second_measurement['percentage'], 'o-', color='green')
plt.show()
Run Code Online (Sandbox Code Playgroud)

这只会改变 的颜色servers_df.plot。如果您想更改其他两个的颜色,您可以采用相同的逻辑:创建一个您希望它们在每次迭代时采用的颜色列表,迭代该列表并将颜色值传递给color每次迭代的参数。