我正在尝试计算一系列变化的百分比变化(大于1的周期),并且在系列结束时出现窗口缩小的情况。
以下示例无法产生预期的结果:
import pandas as pd
import numpy as np
labels = ['A', 'A', 'A', 'A', 'A', 'B', 'A', 'C', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'B']
prices = [62, 55, 55, 74, 31, 77, 20, 21, 25, 30, 21, 35, 66, 12, 1, 2, 4]
df = pd.DataFrame(data = {'label':labels,'price': price}, columns = ['label', 'price'])
df['price_chg'] = df.groupby('label')['price'].transform(lambda x: x.pct_change(3, fill_method=None).shift(-3))
df = df.iloc[np.lexsort((df.index, df['label'].values))]
df
label price price_chg
0 A 62 0.193548
1 A 55 -0.436364
2 A 55 -0.636364
3 A 74 NaN
4 A 31 NaN
6 A 20 NaN
5 B 77 -0.727273
8 B 25 0.400000
9 B 30 -0.866667
10 B 21 NaN
11 B 35 NaN
16 B 4 NaN
7 C 21 -0.952381
12 C 66 -0.969697
13 C 12 NaN
14 C 1 NaN
15 C 2 NaN
所需结果:
label price price_chg
0 A 62 0.193548
1 A 55 -0.436364
2 A 55 -0.636364
3* A 74 -0.729730
4* A 31 -0.354839
6 A 20 NaN
5 B 77 -0.727273
8 B 25 0.400000
9 B 30 -0.866667
10* B 21 -0.809523
11* B 35 -0.885714
16 B 4 NaN
7 C 21 -0.952381
12 C 66 -0.969697
13* C 12 -0.833333
14* C 1 1.000000
15 C 2 NaN
在期望的结果中,百分比变化计算继续超过组“ A”的索引2。因此,索引3和索引4的值计算如下:
df.loc[3,['price_chg']] = float(df.loc[6,['price']] / df.loc[3,['price']] - 1)
-0.729730
df.loc[4,['price_chg']] = float(df.loc[6,['price']] / df.loc[4,['price']] - 1)
-0.354839
对于索引10和11(标签“ B”)的值类似:
df.loc[10,['price_chg']] = float(df.loc[16,['price']] / df.loc[10,['price']] - 1)
-0.809523
df.loc[11,['price_chg']] = float(df.loc[16,['price']] / df.loc[11,['price']] - 1)
-0.885714
以及类似的标签“ C”。
我当时想做一个自定义的滑动窗口函数,或者一种将序列的最后一个值重复所需次数(虚拟扩展)的方法,但是我不熟悉如何完成此操作。由于我要处理大量pct_change()周期和大量数据,因此我认为自定义滑动窗口方法可能会更快,因此比扩展序列更可取。
谢谢!
答案 0 :(得分:1)
我认为主要的问题是计算百分比然后进行平移会导致NaN
填充极端值。
您的问题的一种解决方案是使用pandas.DataFrame.shift
计算百分比:
df['price_chg'] = df.groupby('label')['price'].transform(
lambda x: (x.shift(-3).ffill(limit=2)-x)/x)
x.shift(-3).ffill(limit=2)
:在此表达式中,我们向后移动行,并用标签可用的最后一个值填充出现的nan值。我们的最大填充量将为两行,因为当我们向前填充时,最后一行将对应于period = 0(pct_change = 0),这是不希望的。
然后df
将是:
> df
label price price_chg
0 A 62 0.193548
1 A 55 -0.436364
2 A 55 -0.636364
3 A 74 -0.729730
4 A 31 -0.354839
6 A 20 NaN
5 B 77 -0.727273
8 B 25 0.400000
9 B 30 -0.866667
10 B 21 -0.809524
11 B 35 -0.885714
16 B 4 NaN
7 C 21 -0.952381
12 C 66 -0.969697
13 C 12 -0.833333
14 C 1 1.000000
15 C 2 NaN