Все.
У меня есть отсортированный временной ряд my_ts
, и мне нужно найти парные различия (ниже некоторого порога, называемого horizon
) между всеми элементами серии (и не только между последовательными элементами).
Для этого я написал следующий код, но, как вы можете видеть, он применяет itertools , который кажется ненужным в среде pandas.
from itertools import combinations
my_ts = pd.Series(pd.date_range('1/1/2018', periods=6, freq='d'))
def count_gaps(ts, horizon):
# returns counts of all gaps shorter than horizon
diffs = ((t2-t1) for (t1, t2) in combinations(ts, 2) if t2-t1<=horizon)
return pd.Series(diffs).value_counts()
count_gaps(my_ts, horizon=pd.to_timedelta(3, unit='d'))
Есть предложения для более пандаистического (и, надеюсь, более быстрого) решения?
2 ответа
Я думаю, что вы можете
s=pd.DataFrame(columns=my_ts,index=my_ts).apply(lambda x : x.name-x.index)
s.mask((s<pd.Timedelta('1 days'))|(s>pd.Timedelta('3 days'))).stack().value_counts()
Out[528]:
1 days 5
2 days 4
3 days 3
dtype: int64
Вот значительно более быстрое (около x100 в быстром тесте ниже) решение NumPy:
import numpy as np
import pandas as pd
def count_gaps1(ts, horizon):
diffs = ts.values[:, np.newaxis] - ts.values[np.newaxis, :]
idx, c = np.unique(diffs[(diffs > np.timedelta64(0)) & (diffs <= horizon.to_timedelta64())], return_counts=True)
return pd.Series(c, idx)
my_ts = pd.Series(pd.date_range('1/1/2018', periods=6, freq='d'))
print(count_gaps(my_ts, horizon=pd.to_timedelta(3, unit='d')))
Выход:
1 days 5
2 days 4
3 days 3
dtype: int64
Тест IPython %timeit
:
import itertools
import numpy as np
import pandas as pd
def count_gaps_original(ts, horizon):
diffs = ((t2-t1) for (t1, t2) in itertools.combinations(ts, 2) if t2-t1<=horizon)
return pd.Series(diffs).value_counts()
def count_gaps_Wen(ts, horizon):
s = pd.DataFrame(columns=my_ts,index=my_ts).apply(lambda x : x.name-x.index)
return s.mask((s < pd.Timedelta('1 days')) | (s > pd.Timedelta('3 days'))).stack().value_counts()
def count_gaps_jdehesa(ts, horizon):
diffs = ts.values[:, np.newaxis] - ts.values[np.newaxis, :]
idx, c = np.unique(diffs[(diffs > np.timedelta64(0)) & (diffs <= horizon.to_timedelta64())], return_counts=True)
return pd.Series(c, idx)
my_ts = pd.Series(pd.date_range('1/1/2018', periods=100, freq='d'))
%timeit count_gaps_original(my_ts, horizon=pd.to_timedelta(3, unit='d'))
>>> 145 ms ± 1.87 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit count_gaps_Wen(my_ts, horizon=pd.to_timedelta(3, unit='d'))
>>> 44.1 ms ± 942 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit count_gaps_jdehesa(my_ts, horizon=pd.to_timedelta(3, unit='d'))
>>> 409 µs ± 9.19 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.