Линейный график Matplot pandas кадра данных с двойной шкалой оси Y и датой и временем на оси X - PullRequest
0 голосов
/ 09 января 2020

У меня есть журнал, который описывает мои домашние скорости 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

(для полного файла примера -> https://www.dropbox.com/s/tfmj9ozxe5millx/test.log?dl=0 для вас для загрузки приведенного ниже кода)

I w * sh для построения диаграммы с графиком со скоростями загрузки по левой оси, скоростями загрузки (которые находятся в меньшем и нижнем диапазоне значений) и имеют укороченные даты под отметками 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()

Сейчас я получаю нужный мне график, но был бы признателен за разъяснения о роли осей топора, y1 и y2 в приведенном выше коде. .

Ответы [ 2 ]

2 голосов
/ 09 января 2020

Во-первых, присваивать y1 и y2 объекты не нужно, так как вы никогда не будете использовать их позже. Кроме того, legend=True является значением по умолчанию.

  • За matplotlib.pyplot.subplots документы, возврат ax:

    ax: axes.Axes объект или массив объектов Axes

  • Per pandas .DataFrame.plot , аргумент ax:

    ax: объект осей matplotlib, по умолчанию нет

Следовательно, вы сначала инициализируете массив объектов осей (по умолчанию один элемент, * 1032) * и nrow=2), а затем присваивая его / их в соответствии с pandas графиками. Теперь, как правило, вы переписываете назначение топора с помощью 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()

Single Plot


Чтобы проиллюстрировать, как можно расширять объекты осей, см. Ниже несколько (не перекрывающихся) графиков.

Пример нескольких вспомогательных участков с использованием 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()

two row subplots


Пример нескольких графиков с использованием 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()

two column subplots


Вы можете даже использовать 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()

Pandas subplots output

0 голосов
/ 09 января 2020

Так что, благодаря @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()

Что дает: output of code above

Что я до сих пор не понимаю: а) почему только метка оси X кажется, что цвет соответствует, но не строковому значению :( b) почему параметры ylim = (n, m) на графике df не работают должным образом, и вместо этого я должен использовать конструкции ax.set_ylim

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...