fill_between с datetime64 [ns] [duplicate]

Я написал самый простой (хотя мне не нужна точка в нем).

^([0-9\(\)\/\+ \-]*)$

Как указано ниже, он проверяет только символы, а не его структуру / порядок

25
задан chilliq 29 March 2015 в 13:31
поделиться

3 ответа

Pandas регистрирует конвертер в matplotlib.units.registry, который преобразует количество типов datetime (таких как pandas DatetimeIndex и numpy массивы dtype datetime64) в данные matplotlib, но не обрабатывает Pandas Series с dtype datetime64.

In [67]: import pandas.tseries.converter as converter

In [68]: c = converter.DatetimeConverter()

In [69]: type(c.convert(df['Date'].values, None, None))
Out[69]: numpy.ndarray              # converted (good)

In [70]: type(c.convert(df['Date'], None, None))
Out[70]: pandas.core.series.Series  # left unchanged

fill_between проверяет и использует конвертер для обработки данных, если он существует.

Итак, в качестве обходного пути вы можете преобразовать даты в массив NumPy из datetime64:

d = data['Date'].values
plt.fill_between(d, data['A'], data['B'],
                where=data['A'] >= data['B'],
                facecolor='green', alpha=0.2, interpolate=True)

Например,

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

N = 300
dates = pd.date_range('2000-1-1', periods=N, freq='D')
x = np.linspace(0, 2*np.pi, N)
data = pd.DataFrame({'A': np.sin(x), 'B': np.cos(x),
               'Date': dates})
plt.plot_date(data['Date'], data['A'], '-')
plt.plot_date(data['Date'], data['B'], '-')

d = data['Date'].values
plt.fill_between(d, data['A'], data['B'],
                where=data['A'] >= data['B'],
                facecolor='green', alpha=0.2, interpolate=True)
plt.xticks(rotation=25)
plt.show()

enter image description here [/g1]

20
ответ дан unutbu 21 August 2018 в 10:11
поделиться
  • 1
    Обходной путь работает отлично - большое вам спасибо. Такое поведение довольно странно, что может быть причиной здесь? – chilliq 29 March 2015 в 13:45
  • 2
    @chilliq: Мое первое предложение заключалось в использовании DatetimeIndex. Оказывается, это не обязательно. Быстрее просто использовать data['Date'].values для извлечения базового массива NumPy из серии Pandas. – unutbu 29 March 2015 в 14:31
  • 3
    Это очень полезно, я не знал об этом. Я считаю, что этот небольшой трюк будет решать многие из моих проблем с построением кадров данных с помощью Matplotlib. – chilliq 29 March 2015 в 14:39
  • 4
    Bizarre, но это работает с% matplotlib qt, но не встроенным – AimForClarity 14 August 2018 в 11:13
  • 5

Я столкнулся с этой проблемой после обновления до Pandas 0.21. Ранее мой код работал с fill_between(), но после обновления.

Оказывается, что это исправление, упомянутое в ответе @unutbu, которое было тем, что у меня было до сих пор, работает только в том случае, если DatetimeIndex содержит объекты date, а не datetime объекты, имеющие время Информация.

Глядя на пример выше, я попытался добавить следующую строку перед вызовом fill_between():

d['Date'] = [z.date() for z in d['Date']]
4
ответ дан Igor Raush 21 August 2018 в 10:11
поделиться

Как отметил WillZ, Pandas 0.21 нарушил обходное решение unutbu. Однако преобразование дат к датам может оказать значительное негативное влияние на анализ данных. Это решение в настоящее время работает и поддерживает datetime:

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

N = 300
dates = pd.date_range('2000-1-1', periods=N, freq='ms')
x = np.linspace(0, 2*np.pi, N)
data = pd.DataFrame({'A': np.sin(x), 'B': np.cos(x),
           'Date': dates})
d = data['Date'].dt.to_pydatetime()
plt.plot_date(d, data['A'], '-')
plt.plot_date(d, data['B'], '-')


plt.fill_between(d, data['A'], data['B'],
            where=data['A'] >= data['B'],
            facecolor='green', alpha=0.2, interpolate=True)
plt.xticks(rotation=25)
plt.show()

EDIT: Согласно комментарию джедая, я решил определить самый быстрый подход трех ниже:

  • method1 = оригинальный ответ
  • method2 = комментарий jedi + оригинальный ответ
  • method3 = комментарий jedi

method2 был немного быстрее, но гораздо более последовательным, и поэтому я отредактировал вышеупомянутый ответ, чтобы отразить наилучший подход.

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


N = 300
dates = pd.date_range('2000-1-1', periods=N, freq='ms')
x = np.linspace(0, 2*np.pi, N)
data = pd.DataFrame({'A': np.sin(x), 'B': np.cos(x),
           'Date': dates})
time_data = pd.DataFrame(columns=['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'])
method1 = []
method2 = []
method3 = []
for i in range(0, 10):
    start = time.clock()
    for i in range(0, 500):
        d = [pd.Timestamp(x).to_pydatetime() for x in data['Date']]
        #d = data['Date'].dt.to_pydatetime()
        plt.plot_date(d, data['A'], '-')
        plt.plot_date(d, data['B'], '-')


        plt.fill_between(d, data['A'], data['B'],
            where=data['A'] >= data['B'],
            facecolor='green', alpha=0.2, interpolate=True)
        plt.xticks(rotation=25)
        plt.gcf().clear()
    method1.append(time.clock() - start)

for i  in range(0, 10):
    start = time.clock()
    for i in range(0, 500):
        #d = [pd.Timestamp(x).to_pydatetime() for x in data['Date']]
        d = data['Date'].dt.to_pydatetime()
        plt.plot_date(d, data['A'], '-')
        plt.plot_date(d, data['B'], '-')


        plt.fill_between(d, data['A'], data['B'],
            where=data['A'] >= data['B'],
            facecolor='green', alpha=0.2, interpolate=True)
        plt.xticks(rotation=25)
        plt.gcf().clear()
    method2.append(time.clock() - start)

for i in range(0, 10):
    start = time.clock()
    for i in range(0, 500):
        #d = [pd.Timestamp(x).to_pydatetime() for x in data['Date']]
        #d = data['Date'].dt.to_pydatetime()
        plt.plot_date(data['Date'].dt.to_pydatetime(), data['A'], '-')
        plt.plot_date(data['Date'].dt.to_pydatetime(), data['B'], '-')


        plt.fill_between(data['Date'].dt.to_pydatetime(), data['A'], data['B'],
            where=data['A'] >= data['B'],
            facecolor='green', alpha=0.2, interpolate=True)
        plt.xticks(rotation=25)
        plt.gcf().clear()
    method3.append(time.clock() - start)

time_data.loc['method1'] = method1
time_data.loc['method2'] = method2
time_data.loc['method3'] = method3
print(time_data)
plt.errorbar(time_data.index, time_data.mean(axis=1), yerr=time_data.std(axis=1))

5
ответ дан TurnipEntropy 21 August 2018 в 10:11
поделиться
  • 1
    Это более быстрый & amp; более простой обходной путь plt.fill_between( data['Date'].dt.to_pydatetime(), .... Это также работает с axes.fill_between. – jedi 28 December 2017 в 03:07
  • 2
    @jedi Спасибо за рекомендацию. Я отредактировал ответ в ответ на ваш комментарий. – TurnipEntropy 29 December 2017 в 17:38
Другие вопросы по тегам:

Похожие вопросы: