Мне нужно сопоставить каждый час месяца с месячной суммой за месяц, к которому относится этот час.
Мне передан DataFrame (monthly_totals
) с основанным на времени pandas.IntervalIndex
,и второй DataFrame (hours
) с pandas.DatetimeIndex
.В более общем случае мне нужно сопоставить индекс одного DataFrame с интервалом другого DataFrame, в который попадает каждая запись.
У меня есть рабочее решение, использующее pandas.Series.apply
, но оно довольно медленное.Я вижу, что numpy.digitize существует, и это насмехается надо мной, потому что параметр bins
должен быть массивом, а не IntervalIndex.
Моя первая попытка, которая работает, но занимает около1 секунда для обработки DataFrame длины 8760 выглядит следующим образом:
def get_mock_montly_totals(self):
start = '2018-07-01'
end = '2019-07-01'
hourly_rng = pd.date_range(start, end, freq='H')
monthly_rng = pd.date_range(start, end, freq='MS')
mock_series = pd.Series(1, index=hourly_rng)
bins = (monthly_rng + pd.offsets.Day(pd.Timestamp(start).day - 1))
cuts = pd.cut(mock_series.index, bins, right=False)
groups = mock_series.groupby(cuts)
monthly_totals = groups.sum()
return monthly_totals
def get_interval_value(self, frame, key):
try:
return frame.iloc[frame.index.get_loc(key)]
except KeyError:
return np.nan
result = api.get_secret_data().resample('H').asfreq()
hours = result.index.to_series()
monthly_totals = self.get_mock_montly_totals()
# This line takes over a second to run, which is too slow.
result['monthly_totals'] = hours.apply(
lambda h: self.get_interval_value(monthly_totals, h))
Где monthly_totals
выглядит так:
[2018-07-01, 2018-08-01) 744
[2018-08-01, 2018-09-01) 744
[2018-09-01, 2018-10-01) 720
[2018-10-01, 2018-11-01) 744
[2018-11-01, 2018-12-01) 720
[2018-12-01, 2019-01-01) 744
[2019-01-01, 2019-02-01) 744
[2019-02-01, 2019-03-01) 672
[2019-03-01, 2019-04-01) 744
[2019-04-01, 2019-05-01) 720
[2019-05-01, 2019-06-01) 744
[2019-06-01, 2019-07-01) 720
dtype: int64
hours
выглядит так:
time
2018-06-27 00:00:00-10:00 2018-06-27 10:00:00
...
2019-06-24 21:00:00-10:00 2019-06-25 07:00:00
И вывод result['monthly_totals']
должен выглядеть следующим образом:
time
2018-06-27 00:00:00-10:00 NaN
...
2019-06-24 20:00:00-10:00 720
2019-06-24 21:00:00-10:00 720
Опять же, мое решение работает, но вызов apply
, кажется, делает его медленным.Поэтому я действительно хочу получить помощь в поиске более чистого решения, которое бросает это.Спасибо!