我在['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
答案 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})