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)
听起来您正在寻找的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)
聚会迟到了,但我遇到了类似的问题,我想与您分享我的解决方案,以防它对任何人有帮助。
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 |
您可以通过以下方式执行您所要求的操作:
pd.DataFrame按列分组security,price窗口操作,apply扩展窗口操作并将步骤 1 中定义的自定义变体函数作为参数传递,pd.DataFrame。或者,您可以通过调用 ,将步骤 3 中的扩展窗口操作替换为滚动.rolling(window=2, min_periods=2)窗口操作,以获得每个证券价格的逐步变化。window=2定义窗口的大小,以便在每次迭代时返回两个元素,并设置计算所需的最小数据(如果否则,min_periods=2将导致)。NaN
您的变体函数应接受一个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)
pd.DataFrame按security列分组接下来,您应该调用按列.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)
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 |
正如您在 .4 中看到的,数据以多索引的形式呈现。我们通过调用 来摆脱外部索引级别('AAPL'、'IBM').droplevel(0),以准备数据以将其正确合并到原始数据帧中。
variations = grouped_variations.droplevel(0)
Run Code Online (Sandbox Code Playgroud)
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 |
| 归档时间: |
|
| 查看次数: |
5208 次 |
| 最近记录: |