在日期时间索引上减去具有不同粒度的数据帧列



我有一些价格数据(例如来自雅虎财经(,将每日粒度日期时间变量作为索引,让我们称之为 df,假设它是微软收盘价作为价值变量。为了获得每月平均收盘价,我显然可以做以下两个之一:

import yfinance as yf
import pandas as pd
df = yf.download("CMG", start="2012-01-01",end="2020-01-01" )
dfm = df.resample("M").mean()
dfm2 = df.groupby(df.index.to_period("M")).mean()

对我来说,它们看起来非常相似,我能说的唯一区别是,在重新采样时,新的日期时间索引是月底,而分组to_period的索引将为 yyyy-mm。

我现在想在 df 中添加一列,具有每日粒度,每个每日收盘价都偏离其月平均值。所以 1/jan/2020 - 平均值(1 月 20 日(,2/1 月/2020 - 平均值(1 月 20 日(,1/Feb/2020 - 平均值(2 月 20 日(。

因为 dfm 和 df 有不同的索引,所以我不能只做 df-dfm。

我唯一能想到的就是遍历 df,在 dfm 上放一个计数器,并在循环中放一个 if 语句,这在很大程度上是一种 c 类型的方法,但不是很pythonic。我想它看起来像这样(但这不起作用(:

counter = 0
df["dailyminusmonthly"] =""
for i in df:
if i.index <= dfm[counter].index:
i.dailyminusmonthly = i.close - dfm.close[counter]
else:
counter = counter +1
i.dailyminusmonthly = i.close - dfm.close[counter]

您可以将DatetimeIndex转换为月期,因此您可以减去dfm2,只有这样才需要转换为numpy数组,因为减去Series的索引与原始df不同,以防止完整的NaNs列:

df['dailyminusmonthly1']= (df['Close'].to_period('M')
.sub(df.groupby(df.index.to_period("M"))['Close'].mean())
.to_numpy())

另一个更简单的解决方案是使用与 original 相同的索引Resampler.transform

df['dailyminusmonthly2']= df['Close'].sub(df.resample("M")['Close'].transform('mean'))

print (df)
Open        High         Low       Close   Adj Close  
Date                                                                     
2012-01-03  343.700012  350.489990  340.000000  341.269989  341.269989   
2012-01-04  346.000000  349.980011  345.010010  348.750000  348.750000   
2012-01-05  346.880005  351.980011  342.570007  350.480011  350.480011   
2012-01-06  348.880005  352.630005  347.350006  348.950012  348.950012   
2012-01-09  349.000000  349.489990  336.290009  339.739990  339.739990   
...         ...         ...         ...         ...   
2019-12-24  827.099976  829.409973  823.159973  828.890015  828.890015   
2019-12-26  829.409973  839.280029  828.239990  838.599976  838.599976   
2019-12-27  839.969971  840.000000  835.000000  836.789978  836.789978   
2019-12-30  838.169983  838.750000  829.010010  836.070007  836.070007   
2019-12-31  837.239990  842.270020  833.359985  837.109985  837.109985   
Volume  dailyminusmonthly1  dailyminusmonthly2  
Date                                                        
2012-01-03  728100          -13.559013          -13.559013  
2012-01-04  743100           -6.079002           -6.079002  
2012-01-05  672300           -4.348991           -4.348991  
2012-01-06  370700           -5.878990           -5.878990  
2012-01-09  748600          -15.089012          -15.089012  
...                 ...                 ...  
2019-12-24   91900            3.640494            3.640494  
2019-12-26  255400           13.350455           13.350455  
2019-12-27  201900           11.540458           11.540458  
2019-12-30  211400           10.820487           10.820487  
2019-12-31  282200           11.860465           11.860465  
[2012 rows x 8 columns]

最新更新