Временные ряды странных интерполяций в python matplotlib - PullRequest
0 голосов
/ 19 октября 2019

Я новичок в matplotlib и работаю с данными, значения которых указаны только с интервалом от 9 до 5 с понедельника по пятницу.

Когда я пытаюсь построить данные, я замечаю, что между пропущенными значениями между 17:00 и 9:00 в следующий рабочий день есть интерполяции из-за внезапного включения matplotlib пропущенного datetime.

Моя цель здесь:

1) добавить вертикальные пунктирные линии в левой части несплошностей

2) удалить интерполяции


Ниже приведен фрагмент кода, с которым я работаю. Код сгенерирует два графика.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from datetime import datetime


x_var1= pd.date_range(datetime(2014, 1, 14, 9, 0),datetime(2014, 1, 21, 17, 0),
                   freq="30min",
                   tz= 'US/Pacific',
                   closed= 'left'
                   )

x_var1 = x_var1[x_var1.dayofweek < 5]
x_var1= x_var1[x_var1.indexer_between_time('9:00','17:00', include_end= False)]
x_var1= x_var1[x_var1.hour != 12]

np.random.seed(0)
y_var2= np.random.normal(loc= 40, scale= 4.4, size= len(x_var1))
fig, ax= plt.subplots(nrows= 2, ncols= 1)

ax[0].plot(x_var1, y_var2)
ax[0].set_title("This plot has extra interpolation that needs to be removed and needs vertical dotted lines for discontinuities")


x_var2= np.arange(len(x_var1))
ax[1].plot(x_var2, y_var2)
ax[1].set_title("this plot only needs correct xaxis and added vertical dotted lines for discontinuities")

plt.show()

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


РЕДАКТИРОВАТЬ: изменил набор данных примера на более случайный, который лучше отражает реальную проблему. Также включен перерыв на обед, поэтому будут отсутствовать данные между 12:00 и 12:59

enter image description here

Ответы [ 2 ]

1 голос
/ 19 октября 2019

Хорошо, это то, что вы ищете?

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

x_var1= pd.date_range(pd.to_datetime('2014-01-14 09:00:00'), pd.to_datetime('2014-01-21 17:00:00'),
                   freq="30min",
                   tz= 'US/Pacific',
                   closed= 'left'
                   )

x_var1 = x_var1[x_var1.dayofweek < 5]
x_var1= x_var1[x_var1.indexer_between_time('9:00','17:00', include_end= True)]
x_var1= x_var1[x_var1.hour != 12]

np.random.seed(0)
y_var2= np.random.normal(loc= 40, scale= 4.4, size= len(x_var1))

df = pd.DataFrame(index=x_var1, data=y_var2)

# mpl won't plot between nan values
df[(df.index.hour == 17) & (df.index.minute == 0)] = np.nan
df[(df.index.hour == 9) & (df.index.minute == 0)] = np.nan
fig, ax = plt.subplots()
df.plot(ax=ax, legend=False)
df[(df.index.hour == 9) & (df.index.minute == 0)] = 0

# we know the discontinuities occur at the end of the days
[plt.axvline(d, ls='--') for d, v in list(zip(df.index, df.iloc[:, 0])) if pd.isnull(v)]

enter image description here

1 голос
/ 19 октября 2019

Вот как бы я это сделал. Не уверен, что я поставлю вертикальные линии на правильные разрывы, но, надеюсь, вы получите идею:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

x_var1= pd.date_range(pd.to_datetime('2014-01-14 09:00:00'), pd.to_datetime('2014-01-21 17:00:00'),
                   freq="30min",
                   tz= 'US/Pacific',
                   closed= 'left'
                   )
x_var1 = x_var1[x_var1.dayofweek < 5]
x_var1= x_var1[x_var1.indexer_between_time('9:00','17:00', include_end= True)]

df = pd.DataFrame(index=x_var1, data=[np.nan]*len(x_var1))
df.iloc[0, 0] = 0
df.iloc[-1, 0] = 100
# to get line with "slope of 1"
df = df.interpolate(method='time')

# mpl won't plot between nan values
df[(df.index.hour == 17) & (df.index.minute == 0)] = np.nan
df[(df.index.hour == 9) & (df.index.minute == 0)] = np.nan
fig, ax = plt.subplots()
df.plot(ax=ax, legend=False)
df[(df.index.hour == 9) & (df.index.minute == 0)] = 0

# we know the discontinuities occur at the end of the days
[plt.axvline(d, ls='--') for d, v in list(zip(df.index, df.iloc[:, 0])) if pd.isnull(v)]

Вывод:

enter image description here

...