2017-02-20 137 views
4

我在['符号']列中确定以下时间序列中的正面和负面时间段。我怎样才能得到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']) 

UPDATE: 我意识到,需要周期其中sign = '1',并签署=单独的计数 '-1',当涉及持续时间。这是对'1'和'-1'时期的描述性统计。

大熊猫版本:0.19.2

+0

对于UPDATE部分,你可以添加一个样本和预期的o/p? – Divakar

+0

In [1]:duration_up_count(a) Out [2]:(array([5,2]))使用你的数组,等价于down。然后跳过累计计数。 – cJc

回答

3

您可以使用diff()和随后cumsum()得到的差异在系列中,并相应地groupby。

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的指数,然后通过consecutives分组。

>>> 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的专家,所以没有关于此的性能保证。

+0

当我从我的问题的数据框上运行你的函数时,我得到以下代码的错误信息:cnts = df.sign.iloc [diffs.drop_duplicates()。索引] .value_counts()。to_dict()错误消息:TypeError:无效类型促销 – cJc

+0

@cJc您正在使用哪种版本的熊猫? – miradulo

+0

我意识到,在持续时间方面,需要单独计算sign ='1'和sign ='-1'的期间。这是对'1'和'-1'时期的描述性统计。 – cJc

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}) 
+0

请参阅更新后的问题:我意识到,在持续时间方面,需要单独计数sign ='1'和sign ='-1'的期间。这是对'1'和'-1'时期的描述性统计。 – cJc