MatplotlibPandas Dataframe 线图,双Y轴刻度,X轴为日期时间

68de4m5k  于 2022-11-24  发布在  其他
关注(0)|答案(2)|浏览(90)

我有一个日志,它描述了我家的ADSL速度。日志条目的格式如下,其中字段是日期时间;降速;加速;测试主机:

2020-01-06 18:09:45;INFO;211.5;29.1;0;host:spd-pub-rm-01-01.fastwebnet.it
2020-01-06 18:14:39;WARNING;209.9;28.1;0;host:spd-pub-rm-01-01.fastwebnet.it
2020-01-08 10:51:27;INFO;211.6;29.4;0;host:spd-pub-rm-01-01.fastwebnet.it

(for一个完整的示例文件-〉https://www.dropbox.com/s/tfmj9ozxe5millx/test.log?dl=0,供您下载下面的代码)
我希望绘制一个matplot图,其中左轴为下载速度,上传速度(其值范围较小且较低),x刻度标记下方的缩短日期时间可能为45度角。

"""Plots the adsl-log generated log."""
import matplotlib.pyplot as plt
# import matplotlib.dates as mdates
import pandas as pd

# set field delimiter and set column names which will also cause reading from row 1
data = pd.read_csv("test.log", sep=';', names=[
                   'datetime', 'severity', 'down', 'up', 'loss', 'server'])

#  we need to filter out ERROR records (with 0 speeds)
indexNames = data[data['severity'] == 'ERROR'].index
data.drop(indexNames, inplace=True)

# convert datetime pandas objecti to datetime64
data['datetime'] = pd.to_datetime(data['datetime'])

# use a dataframe with just the data I need; cleaner
speeds_df = data[['datetime', 'down', 'up']]
speeds_df.info() # this shows datetime column is really a datetime64 value now
# now let's plot
fig, ax = plt.subplots()
y1 = speeds_df.plot(ax=ax, x='datetime', y='down', grid=True, label="DL", legend=True, linewidth=2,ylim=(100,225))
y2 = speeds_df.plot(ax=ax, x='datetime', y='up', secondary_y=True, label="UL", legend=True, linewidth=2, ylim=(100,225))

plt.show()

我现在得到了我需要的图,但希望对上述代码中ax、y1和y2轴的作用进行一些澄清。

enxuqcxy

enxuqcxy1#

首先,没有必要分配 y1y2 对象,因为以后永远不会使用它们。另外,legend=True是默认值。

ax:axes。Axes对象或Axes对象数组

ax:matplotlib轴对象,默认为无
因此,首先初始化一个axis对象数组(默认为nrow=1nrow=2),然后根据Pandas图对其进行赋值。现在,通常情况下,您会用ax=ax * 覆盖 * ax的赋值,但由于您使用了辅助y轴,图会彼此重叠:

# INITIALIZE FIG DIMENSION AND AXES OBJECTS
fig, axs = plt.subplots(figsize=(8,4))

# ASSIGN AXES OBJECTS ACCORDINGLY
speeds_df.plot(ax=axs, x='datetime', y='down', grid=True, label="DL", linewidth=2, ylim=(100,225))
speeds_df.plot(ax=axs, x='datetime', y='up', secondary_y=True, label="UL", linewidth=2, ylim=(100,225))

plt.show()

要说明如何扩展轴对象,请参阅下面的多个(非重叠)图。
使用nrows=2的多个子区示例:

# INITIALIZE FIG DIMENSION AND AXES OBJECTS
fig, axs = plt.subplots(nrows=2, figsize=(8,4))

# ASSIGN AXES OBJECTS WITH INDEXING AND NO Y LIMITS
speeds_df.plot(ax=axs[0], x='datetime', y='down', grid=True, label="DL", linewidth=2)
plt.subplots_adjust(hspace = 1)
speeds_df.plot(ax=axs[1], x='datetime', y='up', label="UL", linewidth=2)

plt.show()

使用ncols=2的多个绘图示例:

# INITIALIZE FIG DIMENSION AND AXES OBJECTS
fig, axs = plt.subplots(ncols=2, figsize=(12,4))

# ASSIGN AXES OBJECTS WITH INDEXING AND NO Y LIMITS
speeds_df.plot(ax=axs[0], x='datetime', y='down', grid=True, label="DL", linewidth=2)
speeds_df.plot(ax=axs[1], x='datetime', y='up', label="UL", linewidth=2)

plt.show()

您甚至可以在将日期/时间字段设置为索引后使用subplots=True

# INITIALIZE FIG DIMENSION AND AXES OBJECTS
fig, axs = plt.subplots(figsize=(8,4))

# ASSIGN AXES OBJECT PLOTTING ALL COLUMNS
speeds_df.set_index('datetime').plot(ax=axs, subplots=True, grid=True, label="DL", linewidth=2)

plt.show()

uidvcgyl

uidvcgyl2#

所以感谢@Parfait,我希望我理解的东西是正确的。这里是工作代码:

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
###### Prepare the data to plot
# set field delimiter and set column names which will also cause reading from row 1
data = pd.read_csv('test.log', sep=';', names=[
                   'datetime', 'severity', 'down', 'up', 'loss', 'server'])
#  we need to filter out ERROR records (with 0 speeds)
indexNames = data[data['severity'] == 'ERROR'].index
data.drop(indexNames, inplace=True)
# convert datetime pandas object to datetime64
data['datetime'] = pd.to_datetime(data['datetime'])
# use a dataframe with just the data I need; cleaner
speeds_df = data[['datetime', 'down', 'up']]

# now plot the graph
fig, ax = plt.subplots()

color = 'tab:green'
ax.set_xlabel('thislabeldoesnotworkbutcolordoes', color=color)
ax.tick_params(axis='x', labelcolor=color)

color = 'tab:red'
speeds_df.plot(ax=ax, x='datetime', y='down', label="DL", legend=True, linewidth=2, color=color)
ax.set_ylabel('DL', color=color)
ax.tick_params(axis='y', labelcolor=color)

color = 'tab:blue'
ax2 = speeds_df.plot(ax=ax, x='datetime', y='up', secondary_y=True, label="UL", legend=True, linewidth=2, color=color)
ax2.set_ylabel('UL', color=color)
ax2.tick_params(axis='y', labelcolor=color)
# using ylim in the plot command params does not work the same
# cannot show a grid since the two scales are different
ax.set_ylim(10, 225)
ax2.set_ylim(15, 50)

plt.show()

其给出:

我还是不明白的是a)为什么x轴标签似乎只支持颜色而不支持字符串值:(b)为什么df图中的ylim=(n,m)参数不能很好地工作,我必须使用ax.set_ylim结构来代替

相关问题