如何使用熊猫计算与初始值相比的变化百分比?

E.K*_*.K. 2 python percentage dataframe pandas

我有一个DataFrame并且需要计算与公司年初相比的变化百分比。有什么方法可以使用pct_change()或其他方法来执行此任务?谢谢!

df 看起来像

security    date        price
IBM         1/1/2016    100
IBM         1/2/2016    102
IBM         1/3/2016    108
AAPL        1/1/2016    1000
AAPL        1/2/2016    980
AAPL        1/3/2016    1050
AAPL        1/4/2016    1070
Run Code Online (Sandbox Code Playgroud)

我想要的结果

security    date        price   change
IBM         1/1/2016    100     NA
IBM         1/2/2016    102     2%
IBM         1/3/2016    108     8%
AAPL        1/1/2016    1000    NA
AAPL        1/2/2016    980     -2%
AAPL        1/3/2016    1050    5%
AAPL        1/4/2016    1070    7%
Run Code Online (Sandbox Code Playgroud)

Ste*_*fan 5

听起来您正在寻找的expanding_window版本pct_change()。开箱即用的AFAIK并不存在,但是您可以自己动手:

df.groupby('security')['price'].apply(lambda x: x.div(x.iloc[0]).subtract(1).mul(100))
Run Code Online (Sandbox Code Playgroud)


Gon*_*oro 5

聚会迟到了,但我遇到了类似的问题,我想与您分享我的解决方案,以防它对任何人有帮助。

TL; DR

def get_variation(values: pd.Series) -> np.float64:
    base = values.iloc[0]  # first element in window iteration
    current = values.iloc[-1]  # last element in window iteration

    return (current - base) / base if base else 0  # avoid ZeroDivisionError

variations = df.groupby('security')['price'].expanding(min_periods=2).apply(get_variation)
df = df.assign(change=variations.droplevel(0))
Run Code Online (Sandbox Code Playgroud)
安全 日期 价格 改变
0 国际商业机器公司 2016年1月1日 100
1 国际商业机器公司 2016年1月2日 102 0.02
2 国际商业机器公司 2016年1月3日 108 0.08
3 AAPL 2016年1月1日 1000
4 AAPL 2016年1月2日 980 -0.02
5 AAPL 2016年1月3日 1050 0.05
6 AAPL 2016年1月4日 1070 0.07

您可以通过以下方式执行您所要求的操作:

  1. 定义您自己的变分函数,
  2. pd.DataFrame按列分组security
  3. 对结果列使用扩展price窗口操作,
  4. 调用apply扩展窗口操作并将步骤 1 中定义的自定义变体函数作为参数传递,
  5. 删除结果系列的外部索引,
  6. 将先前的结果分配给original pd.DataFrame

或者,您可以通过调用 ,将步骤 3 中的扩展窗口操作替换为滚动.rolling(window=2, min_periods=2)窗口操作,以获得每个证券价格的逐步变化。window=2定义窗口的大小,以便在每次迭代时返回两个元素,并设置计算所需的最小数据(如果否则,min_periods=2将导致)。NaN

一步步

1. 定义自己的变分函数

您的变体函数应接受一个pd.Series参数作为参数,并使用集合中的第一项和最后一项来计算变体。在这里,我使用金融中使用的标准变差函数来计算利率。最后一行有一个if/else要避免的声明ZeroDivisionError

def get_variation(values: pd.Series) -> np.float64:
    base = values.iloc[0]
    current = values.iloc[-1]

    return (current - base) / base if base else 0
Run Code Online (Sandbox Code Playgroud)

2.pd.DataFramesecurity列分组

接下来,您应该调用按列.groupby('security')分组,以便为​​分组计算准备数据。pd.DataFramesecurity

grouped_df = df.groupby('security')
Run Code Online (Sandbox Code Playgroud)
安全 日期 价格 改变
安全
AAPL 3 AAPL 2016年1月1日 1000
4 AAPL 2016年1月2日 980 -0.02
5 AAPL 2016年1月3日 1050 0.05
6 AAPL 2016年1月4日 1070 0.07
国际商业机器公司 0 国际商业机器公司 2016年1月1日 100
1 国际商业机器公司 2016年1月2日 102 0.02
2 国际商业机器公司 2016年1月3日 108 0.08

price3. 对结果列使用扩展窗口操作

.expanding(min_periods=2)接下来,您应该通过调用价格组来使用扩展窗口操作。这将迭代每个price组,并以pd.Series. 您可以调用.expanding(min_periods=n)setn作为每次迭代返回值所需的最小观测数(或者Nan,如果是其他情况)。就您而言,鉴于您NaN对第一条记录有要求,因为它没有与其他任何记录进行比较,您应该通过min_periods=2; 如果您希望得到0结果,请通过min_periods=1

windows = grouped_df['price'].expanding(min_periods=2)
Run Code Online (Sandbox Code Playgroud)

4. 调用apply扩展窗口操作并将步骤 1 中定义的自定义变体函数作为参数传递

调用.apply(get_variation)会将您的自定义变化公式应用于每个结果窗口并返回结果。

grouped_variations = windows.apply(get_variation)
Run Code Online (Sandbox Code Playgroud)
安全
AAPL 3
4 -0.02
5 0.05
6 0.07
国际商业机器公司 0
1 0.02
2 0.08

5. 删除结果序列的外部索引

正如您在 .4 中看到的,数据以多索引的形式呈现。我们通过调用 来摆脱外部索引级别('AAPL'、'IBM').droplevel(0),以准备数据以将其正确合并到原始数据帧中。

variations = grouped_variations.droplevel(0)
Run Code Online (Sandbox Code Playgroud)

6. 将之前的结果分配给原始结果pd.DataFrame

最后,我们通过调用将价格变化分配到原始数据框中df.assign。数据将被连接到其索引上的目的地。

df = df.assign(change=variations)
Run Code Online (Sandbox Code Playgroud)
安全 日期 价格 改变
0 国际商业机器公司 2016年1月1日 100
1 国际商业机器公司 2016年1月2日 102 0.02
2 国际商业机器公司 2016年1月3日 108 0.08
3 AAPL 2016年1月1日 1000
4 AAPL 2016年1月2日 980 -0.02
5 AAPL 2016年1月3日 1050 0.05
6 AAPL 2016年1月4日 1070 0.07