TL;DR
使用 data.servers_df.plot()
始终会创建一个新的图表,而 plt.plot()
则会在最后创建的图表上进行绘制。解决方法是为所有需要绘制的内容创建专用轴。
Preface
假设以下变量:
data.servers_df
:包含两个浮点数列 "time"
和 "percentage"
的数据框架
data.first_measurements
:包含键值 "time"
和 "percentage"
的字典,每个键值都是一组浮点数
data.second_measurements
:包含键值 "time"
和 "percentage"
的字典,每个键值都是一组浮点数
由于没有展示 Graph()
函数的内容,因此跳过了生成 stat_files
,只创建了一个虚拟的数据列表。
如果 data.first_measurements
和 data.second_measurements
也是数据框架,请告诉我,有更好的解决方案。
Theory - Behind the curtains
每个 matplotlib
图表(线条、柱状图等)都存在于一个 matplotlib.axes.Axes
元素上。这些元素就像常规坐标系的轴线一样。现在有两个事情发生了:
- 当使用
plt.plot()
时,没有指定任何轴线,因此 matplotlib 在后台查找当前的轴线元素,如果没有找到,则创建一个空的轴线元素并使用它,并将其设置为默认值。然后第二次调用 plt.plot()
会找到这些轴线并使用它们。
DataFrame.plot()
则总是创建一个新的轴线元素(如果没有通过 ax
参数指定轴线的话)
因此在您的代码中,data.servers_df.plot()
首先在幕后创建了一个轴线元素(这也是默认值),然后以下两个 plt.plot()
调用获取默认轴线并在其上进行绘制,这就是为什么会得到两个图表而不是一个的原因。
Solution
以下解决方案首先使用 plt.subplots()
创建了一个专用的 matplotlib.axes.Axes
元素。然后将该轴线元素用于绘制所有线条。特别注意 data.server_df.plot()
中的 ax=ax
。请注意,我将标记的显示方式从 o-
更改为 o
(因为我们不想显示线条(-
),而只想显示标记(o
))。
以下是虚拟数据:
fig, ax = plt.subplots()
for i, data in enumerate(stat_files):
y_column = f'percentage_{i}'
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()
![在此输入图片描述](https://istack.dev59.com/dYG1z.webp)
模拟数据
import random
import pandas as pd
import matplotlib.pyplot as plt
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)]
fig, ax = plt.subplots()
然后在循环中使用data.servers_df.plot(..., ax=ax)
和ax.plot(...)
。 - Mr. T