Разноцветные линии Matplotlib с осью datetime64 [ns] - PullRequest
1 голос
/ 11 января 2020

Вот упрощенная версия того, что я пытаюсь выполнить sh. Я следую этому примеру многоцветных линий с веб-сайта matplotlib.

Я пытаюсь построить набор данных временных рядов с линией, окрашенной в соответствии с другим массивом. В приведенном ниже простом примере я строю график y = x ^ 2 с затененной линией в соответствии с ее производным, dy / dx = 2x.

Когда я использую ось X только чисел с плавающей точкой, как показано ниже, она работает нормально.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection

# Generate data
x = np.linspace(0,10, 60)
y = x ** 2
dydx = 2*x

# Create arrays needed for multicolored lines
points = np.array([x, y]).T.reshape(-1,1,2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
norm = plt.Normalize(dydx.min(), dydx.max())

# Plot
fig, ax = plt.subplots(1,1, figsize=(10,10))

lc = LineCollection(segments, cmap='jet', norm=norm)
lc.set_array(dydx)
lc.set_linewidth(2)
line = ax.add_collection(lc)
fig.colorbar(line, ax=ax)

ax.set_xlim(x.min(), x.max())
ax.set_ylim(y.min(), y.max())
plt.show()

, которая производит

working graph of y=x^2 with shaded derivative

Однако, если я пытаюсь построить данные временных рядов (где ось x является массивом datetime64 [ns]), это не сработает. В приведенном ниже примере я заменяю x на x_time.

# Generate time array
ts = np.datetime64('2020-01-01T00:00:00')
te = np.datetime64('2020-01-01T01:00:00')
x_time = np.arange(ts, te, np.timedelta64(1,'m'), dtype='datetime64[ns]')

# Create arrays needed for multicolored lines
points = np.array([x_time, y]).T.reshape(-1,1,2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
norm = plt.Normalize(dydx.min(), dydx.max())

# Plot
fig, ax = plt.subplots(1,1, figsize=(10,10))

lc = LineCollection(segments, cmap='jet', norm=norm)
lc.set_array(dydx)
lc.set_linewidth(2)
line = ax.add_collection(lc)
fig.colorbar(line, ax=ax)

ax.set_xlim(x_time.min(), x_time.max())
ax.set_ylim(y.min(), y.max())
plt.show()

, который создает фигуру с правым x с любыми отметками оси y, но без линии

enter image description here

Редактировать: Хорошо, я выяснил, где линия прошла. Когда я создаю массив segments, он преобразует datetime64[ns] в целочисленное представление. Обычно matplotlib может интерпретировать это как дату и время, но в этом случае из-за LineCollection он сохраняет его как int

Установка ax.set_xlim(segments[:,:,0].min(), segments[:,:,0].max()) показывает мою строку, но ось неверна (не покажу как время). enter image description here

1 Ответ

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

Вам нужно будет

  1. Преобразовать даты в числа, представляющие формат даты и времени matplotlib
  2. Скажите оси, что она должна отмечать datetime.

Так :

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import matplotlib.dates as mdates
# Generate data
x = np.linspace(0,10, 60)
y = x ** 2
dydx = 2*x

# Generate time array
ts = np.datetime64('2020-01-01T00:00:00')
te = np.datetime64('2020-01-01T01:00:00')
x_time = np.arange(ts, te, np.timedelta64(1,'m'), dtype='datetime64[ns]')
x_time = mdates.date2num(x_time)
# Create arrays needed for multicolored lines
points = np.array([x_time, y]).T.reshape(-1,1,2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
norm = plt.Normalize(dydx.min(), dydx.max())

# Plot
fig, ax = plt.subplots(1,1, figsize=(10,10))

lc = LineCollection(segments, cmap='jet', norm=norm)
lc.set_array(dydx)
lc.set_linewidth(2)
line = ax.add_collection(lc)
fig.colorbar(line, ax=ax)

ax.xaxis_date()
ax.autoscale()

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