计算 pandas 时间序列趋势的统计数据

Posted

技术标签:

【中文标题】计算 pandas 时间序列趋势的统计数据【英文标题】:Computing statistics on trends in a time series in pandas 【发布时间】:2021-10-11 01:46:27 【问题描述】:

我有一个关于不同时期商品价格的时间序列数据:

import pandas as pd
d = 'ItemID': 0: '1',
1: '1',
2: '1',
3: '1',
4: '1',
5: '1',
6: '1',
7: '1',
8: '1',
9: '1',
10: '1',
11: '2',
12: '2',
13: '2',
14: '2',
15: '2',
16: '2',
17: '2',
18: '2',
19: '2',
20: '2',
21: '2',
'Period': 0: '1',
1: '1',
2: '1',
3: '1',
4: '1',
5: '1',
6: '2',
7: '2',
8: '2',
9: '2',
10: '2',
11: '1',
12: '1',
13: '1',
14: '1',
15: '1',
16: '2',
17: '2',
18: '2',
19: '2',
20: '2',
21: '2',
'Price': 0: 1,
1: 2,
2: 1,
3: 2,
4: 2,
5: 3,
6: 6,
7: 6,
8: 7,
9: 7,
10: 8,
11: 50,
12: 49,
13: 50,
14: 49,
15: 48,
16: 61,
17: 62,
18: 63,
19: 64,
20: 64,
21: 65

df = pd.DataFrame(d)

我想计算以下关于每件商品和期间的价格变化的统计数据:

条纹数 最大条纹长度 平均条纹长度

从本质上讲,连续是一个非递减值或非递增值的列表。在以下列表 [0,5,4,3,3] 中有 2 个条纹:[0,5] 和 [4,3,3]。

对于上述数据框,正确的输出是:

s = 'ItemID': 0: '1',1: '1', 2: '2', 3: '2', 'Period' : 0: '1',1: '2', 2: '1', 3: '2',
     'MaxStreakLength': 0: 4,1: 5, 2: 3, 3: 6,
     'AvgStreakLength': 0: 3,1: 3, 2: 2.5, 3: 6,
     'NumStreaks':0: 2,1: 1, 2: 2, 3: 1

如何有效地做到这一点?初始数据帧非常大(数百万条记录)

【问题讨论】:

如果列表包含[0, 1, 5, 4, 3, 3]怎么办?在这种情况下,你如何定义条纹? @ShubhamSharma 这是两个条纹:一个不减少的 [0,1,5] 和一个不增加的 [4,3,3]。我知道这可能有点惯用 - 5 可以被视为非减少连续的结束和非增加连续的开始。出于实际目的,我会将边框值分配给前面的条纹。 给定的解决方案可能适用于您的情况@Nick,因为您有多个条件它会有点冗长 【参考方案1】:

我假设没有直接的方法来实现这些序列拆分,这里我添加了条件序列拆分,

def sequential_split(p):
    a = p >= 0
    b = a.cumsum()
    arr = b-b.mask(a).ffill().fillna(0).astype(int)
    streak_ends = (np.where(a==0)[0]-1)
    return arr, streak_ends
def get_data(p):
    arr,s_e = sequential_split(p.diff())
    arr1,s_e1 = sequential_split(p.diff(-1))
    if len(s_e)>len(s_e1):
        s_e , arr = s_e1, arr1
        streak_peaks = arr.iloc[s_e].add(1).tolist()
    else:
        streak_peaks = arr.loc[s_e[1:]].add(1).tolist() + [arr.iloc[-1]+1]
    return [arr.max()+1, sum(streak_peaks)/len(streak_peaks), arr[arr==0].shape[0]]

columns=['MaxStreakLength','AvgStreakLength','NumStreaks']
a = df.groupby(['ItemID','Period'])['Price'].apply(get_data)
a.apply(lambda x: pd.Series(x, index=columns)).reset_index()    

输出:

 ItemID Period  MaxStreakLength AvgStreakLength NumStreaks
0   1      1          4.0            3.0         2.0
1   1      2          5.0            5.0         1.0
2   2      1          3.0            2.5         2.0
3   2      2          6.0            6.0          1.0

【讨论】:

以上是关于计算 pandas 时间序列趋势的统计数据的主要内容,如果未能解决你的问题,请参考以下文章

Python/Pandas- 在趋势变化时应用标签(识别数据集中的局部最大值和最小值)

在Python中的Dataframe中查找遵循趋势的值

来自趋势 python 的时间序列拟合值

计算每个集群的时间序列数据的季节性和趋势

在 Pandas 数据框中计算动态时间扭曲距离

使用Pandas数据读取器进行Python回归建模