PANDAS - Цикл двух индексов даты и времени с разными размерами для сравнения дней и значений

Ищите более эффективный способ зацикливания и сравнения значений datetimeindex в двух объектах Series с разными частотами.

Настроить

Представьте себе две серии Pandas, каждая с индексом даты и времени, охватывающим один и тот же период года, но с разными частотами для каждого индекса. Один имеет частоту дней, другой - часы.

range1 = pd.date_range('2016-01-01','2016-12-31', freq='D')
range2 = pd.date_range('2016-01-01','2016-12-31', freq='H')

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

Что я делаю сейчас... медленно.

Прямо сейчас я использую многоуровневые циклы и операторы if (см. Ниже); время выполнения этих циклов кажется чрезмерным (5,45 с на цикл) по сравнению с тем, к чему я привык в операциях Pandas.

for date, val in zip(frame1.index, frame1['data']): # freq = 'D'
    for date2, val2 in zip(frame2.index, frame2['data']): # freq = 'H'
        if date.day == date2.day: # check to see if dates are a match
            if val2 > val: # compare the values
                # append values, etc

Вопрос

Есть ли более эффективный способ использования индекса в кадре 1 для циклического перемещения по индексу в кадре 2 и сравнения значений в каждом кадре для данного дня? В конечном итоге я хочу создать серию значений, где значения frame2 больше значений frame1.

Воспроизводимый (проверенный) пример

Создайте две отдельные серии со случайными данными и назначьте каждому дату и время.

import pandas as pd
import numpy as np

range1 = pd.date_range('2016-01-01','2016-12-31', freq='D')
range2 = pd.date_range('2016-01-01','2016-12-31', freq='H')

frame1 = pd.Series(np.random.rand(366), index=range1)
frame2 = pd.Series(np.random.rand(8761), index=range2)

2 ответа

Решение

Да использовать resample, asfreq а также pd.concat,

Используйте resample, чтобы получить правильную частоту из вашей серии.

asfreq (звучит немного грязно) используется для преобразования обратно в серию с частотой, определенной в resample.

Объединить с frame1, чтобы получить значения бок о бок.

df = pd.concat([frame1,frame2.resample('1D').asfreq()],axis=1)
df.head()

Выход:

                   0         1
2016-01-01  0.147067  0.235858
2016-01-02  0.820398  0.353275
2016-01-03  0.840499  0.186273
2016-01-04  0.505740  0.340201
2016-01-05  0.547840  0.695041

Затем вы можете использовать следующее, чтобы вернуться к вашей серии frame2, превышающей frame1.

df.columns = ['frame1','frame2']
df.query('framed1 < frame2')['frame2']

Все еще не уверен, что вы хотите сделать с информацией. Но я бы сделал:

  • сделать копию frame2
  • разделить его индекс на компонент даты и времени
  • сравнить, указав уровень

frame3 = frame2.copy()
frame3.index = [pd.to_datetime(frame3.index.date), frame.index.time]
results = frame3.lt(frame1, level=0)

results.head()

2016-01-01  00:00:00    True
            01:00:00    True
            02:00:00    True
            03:00:00    True
            04:00:00    True
dtype: bool
Другие вопросы по тегам