Здесь вы можете использовать groupby
вместо resample
:
df = df.groupby(df.index.date).mean()
Это хорошо работает для правила "1D"
, потому что вы можете легко найти уникальные даты в наборе данных. Сроки, это быстрее, чем повторная выборка:
%%timeit
df.resample(rule='1D').mean().dropna(how="all", axis=0, inplace=True)
#2.79 ms ± 77.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit
df.groupby(df.index.date).mean()
#974 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Я также подумал о проверке каждой передискретизированной корзины, чтобы увидеть, пуста ли она перед присоединением, но это паршиво :
%%timeit
pd.DataFrame([d.mean(axis=0).rename(i) for i,d in df.resample(rule="1D") if not d.empty])
#899 ms ± 19.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Я могу представить, что версия groupby
будет более сложной с разными частотами, или скажем, если вы хотите усреднить несколько единиц времени вместо одной (скажем, выполняя здесь "4D"
, возможно, если бы у вас были данные за 2 недели по каждый конец). Но, возможно, это все еще будет возможно либо путем переименования некоторых дат, либо путем использования нескольких атрибутов времени в вызове groupby
.
Я также думал о попытке использовать pd.cut
, но это также значительно хуже (я включите строительную строку df
, чтобы %%timeit
работал, но результаты для resample
по сути такие же, если он также включен туда):
%%timeit
df = pd.DataFrame(index=index, data=data, columns=cols)
dr = pd.date_range(df.index.min(), df.index.max() + pd.Timedelta(days=1), freq='1D') #resample at the desired frequency and add an extra bin to make sure all data is inlcuded
bins = pd.cut(df.index, dr, include_lowest=True, right=False)
df.index = bins.remove_unused_categories()
output = df.groupby(df.index).mean()
#101 ms ± 832 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)