Čo je najrýchlejší spôsob, ako opakovane resample timeseries údajov rovnakého tvaru z hodinové na ročné v jazyku python

0

Otázka

Čo je najrýchlejší spôsob, ako opakovane resample timeseries údajov rovnakého tvaru?

Problém: mám 30 rokov hodinovom timeseries ktoré chcem resample na ročné a kalendárny rok (resample pravidlo "AKO"). Potrebujem na oboch nájsť znamená v každej roka a suma. Nechýbajú žiadne hodín. Potom som musieť urobiť viac než 10 000 krát. Pre skript píšem, to prevzorkovanie krok trvá najviac času a je limitujúcim faktorom, s ohľadom na optimalizáciu behu. Pretože priestupných rokoch, nikto nemôže resample strany v súlade 8760 hodín ako ďalej každý rok má 8784 hodín.

Napríklad kód:

import pandas as pd
import numpy as np
import time

hourly_timeseries = pd.DataFrame(
    index=pd.date_range(
    pd.Timestamp(2020, 1, 1, 0, 0),
    pd.Timestamp(2050, 12, 31, 23, 30),
    freq="60min")
)
hourly_timeseries['value'] = np.random.rand(len(hourly_timeseries))
# Constraints imposed by wider problem:
# 1. each hourly_timeseries is unique
# 2. each hourly_timeseries is the same shape and has the same datetimeindex
# 3. a maximum of 10 timeseries can be grouped as columns in dataframe
start_time = time.perf_counter()
for num in range(100): # setting as 100 so it runs faster, this is 10,000+ in practice
    yearly_timeseries_mean = hourly_timeseries.resample('AS').mean() # resample by calendar year
    yearly_timeseries_sum = hourly_timeseries.resample('AS').sum()
finish_time = time.perf_counter()
print(f"Ran in {start_time - finish_time:0.4f} seconds")
>>> Ran in -3.0516 seconds

Riešenia som preskúmal:

  1. Urobil som niektoré rýchlosť zlepšenia agregáciou viacerých timeseries do dataframe a prevzorkovanie ich v rovnakom čase, avšak v dôsledku obmedzenia set-up širšieho problému som problémov, ja som obmedzený na s 10 timeseries v každej dataframe. Preto sa problém stále stojí: existuje spôsob, ako výrazne urýchliť prevzorkovanie na timeseries údajov, ak viete, tvar poľa bude vždy rovnaký?
  2. Tiež som sa pozrel do použitím numba ale to neznamená, že pandy funkcie rýchlejšie.

Možné riešenia, ktoré zvuk primeraný, ale nemôžem nájsť potom, čo skúmať:

  1. resample 3D pole timeseries dát pomocou numpy
  2. Pamäť index, ktorý sa resampled a potom nejako urobiť každý resample po prvom resample oveľa rýchlejšie

Vďaka za vašu pomoc :)

1

Najlepšiu odpoveď

0

Ako som písal v komentári, pripravil som indexov pre každý rok a použiť ich na výpočet súčtu oveľa za každý rok rýchlejšie.

Ďalej som odstránené zbytočné výpočtu sumy podľa znamenať znovu, namiesto výpočtu znamenať, ako sum/length_of_indices za každý rok.

Pre N=1000 jeho ~9x rýchlejšie

import pandas as pd
import numpy as np
import time

hourly_timeseries = pd.DataFrame(
    index=pd.date_range(
    pd.Timestamp(2020, 1, 1, 0, 0),
    pd.Timestamp(2050, 12, 31, 23, 30),
    freq="60min")
)
hourly_timeseries['value'] = np.random.rand(len(hourly_timeseries))
# Constraints imposed by wider problem:
# 1. each hourly_timeseries is unique
# 2. each hourly_timeseries is the same shape and has the same datetimeindex
# 3. a maximum of 10 timeseries can be grouped as columns in dataframe
start_time = time.perf_counter()
for num in range(100): # setting as 100 so it runs faster, this is 10,000+ in practice
    yearly_timeseries_mean = hourly_timeseries.resample('AS').mean() # resample by calendar year
    yearly_timeseries_sum = hourly_timeseries.resample('AS').sum()
finish_time = time.perf_counter()
print(f"Ran in {finish_time - start_time:0.4f} seconds")


start_time = time.perf_counter()
events_years = hourly_timeseries.index.year
unique_years = np.sort(np.unique(events_years))
indices_per_year = [np.where(events_years == year)[0] for year in unique_years]
len_indices_per_year = np.array([len(year_indices) for year_indices in indices_per_year])
for num in range(100):  # setting as 100 so it runs faster, this is 10,000+ in practice
    temp = hourly_timeseries.values
    yearly_timeseries_sum2 = np.array([np.sum(temp[year_indices]) for year_indices in indices_per_year])
    yearly_timeseries_mean2 = yearly_timeseries_sum2 / len_indices_per_year

finish_time = time.perf_counter()
print(f"Ran in {finish_time - start_time:0.4f} seconds")
assert np.allclose(yearly_timeseries_sum.values.flatten(), yearly_timeseries_sum2)
assert np.allclose(yearly_timeseries_mean.values.flatten(), yearly_timeseries_mean2)
Ran in 0.9950 seconds
Ran in 0.1386 seconds
2021-11-21 21:00:47

V iných jazykoch

Táto stránka je v iných jazykoch

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................