在系列结束时将 data/shrink window 扩展为 pct_change
Extend data/shrink window for pct_change at end of series
我正在尝试计算系列结束时具有收缩 window 效应的百分比变化(对于大于 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'.
我在想自定义滑动 window 函数,或者重复系列的最后一个值所需次数的方法(虚拟扩展),但我不熟悉如何完成这个。由于我使用的是大 pct_change() 周期和大量数据,我认为自定义滑动 window 方法可能更快,因此比扩展系列更可取。
谢谢!
我认为主要问题是计算百分比然后进行移位会使极端值被 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 值。我们的最大填充将是两行,因为当我们向前填充时,最后一行将对应于句点=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
我正在尝试计算系列结束时具有收缩 window 效应的百分比变化(对于大于 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'.
我在想自定义滑动 window 函数,或者重复系列的最后一个值所需次数的方法(虚拟扩展),但我不熟悉如何完成这个。由于我使用的是大 pct_change() 周期和大量数据,我认为自定义滑动 window 方法可能更快,因此比扩展系列更可取。
谢谢!
我认为主要问题是计算百分比然后进行移位会使极端值被 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 值。我们的最大填充将是两行,因为当我们向前填充时,最后一行将对应于句点=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