如何查找Pandas时间序列的事件持续时间

时间:2017-02-20 20:58:37

标签: python pandas numpy

我在['sign']列中的以下时间序列中识别正周期和负周期。如何获得1和-1的每个持续时间,然后计算1和-1的周期数?

因此,如果我在['sign']列中连续五次'1'然后连续三次'-1'后跟两个'1',答案是持续时间:5天,3天和2天。然后计数。 '1':2和'-1':1。

import pandas_datareader.data as web
import datetime as dt
import numpy as np
import pandas as pd

end = dt.datetime(2016, 12, 31)
start = dt.date(end.year-15, end.month, end.day)

aapl = web.DataReader('AAPL', 'yahoo', start, end)['Adj Close']
aapl = pd.DataFrame(aapl)
aapl['ema'] = aapl.ewm(200).mean()
aapl['diff'] = (aapl['Adj Close'] / aapl['ema']) - 1
aapl['sign'] = np.sign(aapl['diff'])

更新 我意识到,当涉及到持续时间时,需要单独的句点计数,其中sign ='1'和sign ='-1'。这是对'1'和'-1'时段进行描述性统计。

熊猫版:0.19.2

2 个答案:

答案 0 :(得分:3)

您可以使用diff()和后续cumsum()来获取系列中的差异,并相应地进行分组。

aapl.groupby((aapl.sign.diff() != 0).cumsum()).size()

至于获取每个标记组的计数,可能有更聪明的方法来执行此操作,但您可以重复使用相同的diff结果来删除重复项后对原始sign系列进行索引

aapl.sign.iloc[(aapl.sign.diff() != 0).cumsum().drop_duplicates().index]
               .value_counts().to_dict()

将这个很好地放在一个函数中可能看起来像

def durs(df):
    diffs = (df.sign.diff() != 0).cumsum()
    cnts = df.sign.iloc[diffs.drop_duplicates().index].value_counts().to_dict()
    days = df.groupby(diffs).size()
    return days, cnts

<强>演示

>>> df
   sign
0     1
1     1
2     1
3     1
4     1
5    -1
6    -1
7    -1
8     1
9     1

>>> days, cnts = durs(df)

>>> days
sign
1    5
2    3
3    2
dtype: int64

>>> cnts
{-1: 1, 1: 2}

<强> 更新

对于您在的评论中添加的请求计算1个句点并随后获得[5, 2]的输出,您可以使用类似的内容,获取1的索引和然后按连续分组。

>>> data = np.where(df.sign == 1)[0]

>>> np.diff(np.r_[0, np.where(np.diff(data) != 1)[0]+1, data.size])
array([5, 2])

请注意,我不是NumPy专家,所以不保证这里的表现。

答案 1 :(得分:1)

这是阵列的一种方法 -

def duration_count(a):
    idx = np.r_[[0],np.flatnonzero(a[1:] != a[:-1])+1,a.size]
    duration = np.diff(idx)
    count = {a[0]:(duration.size+1)//2, -a[0]:duration.size//2}
    return duration, count

样品运行 -

In [43]: a = np.array([1,1,1,1,1,-1,-1,-1,1,1])

In [44]: duration_count(a)
Out[44]: (array([5, 3, 2]), {-1: 1, 1: 2})

In [45]: a = np.array([-1,-1,1,1,1,1,1,-1,-1,-1,1,1,-1,-1,-1,-1])

In [46]: duration_count(a)
Out[46]: (array([2, 5, 3, 2, 4]), {-1: 3, 1: 2})