多索引-熊猫

时间:2018-08-12 07:57:37

标签: python pandas dataframe nan multi-index

我正在尝试用熊猫构建自己的股票筛选器。 我使用晨星公司的DataReader获取数据。 这是我的数据结构:

  • “ Close”,“ Volume”,“ Low”,“ High”等是列;
  • “日期”是行。 我可能是错的,但我选择使用'Symbol'(AAPL,WMLP等)进行索引,而'Date'是索引的子级别。

当我在右侧添加带有一些库存指标(“每日收益”,“滚动平均值20”等)的列时,我遇到了一个主要问题:与其写一个无法计算的Nan值,原因在于没有要使用的先前数据,python使用先前股票的最后数据。参见下面的WMLP在2018-07-02的每日收益表:

df.reset_index(inplace=True)
df.set_index(['Symbol', 'Date'])
                      Close     High       Low        Open    Volume  \
Symbol Date                                                          
AAPL   2018-07-02  187.1800  187.300  183.4200  183.8200  17731343   
       2018-07-03  183.9200  187.950  183.5400  187.7900  13954806   
       2018-07-04  183.9200  183.920  183.9200  183.9200         0   
       2018-07-05  185.4000  186.410  184.2800  185.2600  16604247   
       2018-07-06  187.9700  188.434  185.2000  185.4200  17485245   
WMLP   2018-07-02    1.3700    1.520    1.3300    1.3700      9139   
       2018-07-03    1.4000    1.690    1.3800    1.6900      8075   
       2018-07-04    1.4000    1.400    1.4000    1.4000         0   
       2018-07-05    1.6000    1.600    1.4124    1.4124     29383   
       2018-07-06    1.7095    1.770    1.5200    1.6000     42599   

               Daily Return  
Symbol Date                      
AAPL   2018-07-02           NaN  
       2018-07-03     -0.017416  
       2018-07-04      0.000000  
       2018-07-05      0.008047  
       2018-07-06      0.013862  
WMLP   2018-07-02     -0.992712  
       2018-07-03      0.021898  
       2018-07-04      0.000000  
       2018-07-05      0.142857  
       2018-07-06      0.068437

我希望WMLP在2018-07-02的每日收益为NaN,而无需手动强制执行。

我的索引方法有问题吗?还是建议使用更智能的数据结构来避免此问题? 请注意,我了解面板已弃用,并且尚未学习xarray。

编辑 根据您的要求,请在下面找到开头的其他代码:

start = '2018-07-02'
end = '2018-07-07'
WMLP = web.DataReader('WMLP', 'morningstar', start, end)
AAPL = web.DataReader('AAPL', 'morningstar', start, end)
frames = [AAPL, WMLP]
df = pd.concat(frames)
df['Daily Return'] = df['Close'].pct_change(1)

EDIT :根据Peter(有效的)的回答,我尝试将groupby放在开头仅一次-以使后面的代码更简单易读:

df = df.groupby('Symbol')
df['Daily Return'] = df['Close'].pct_change(1)
df['Rolling 20'] = df['Close'].rolling(20).mean() 

但是这会产生“ TypeError:'DataFrameGroupBy'对象不支持项目分配”

我很感谢groupby解决方案,但也欢迎其他想法

1 个答案:

答案 0 :(得分:0)

您可以df.groupby('Symbol'),然后将pct_change(periods=1)应用于每个组的Close值。从您的MultiIndexed DataFrame df开始:

df['Daily Return'] = df.groupby('Symbol')['Close'].apply(lambda x: x.pct_change(1))
df

                      Close     High       Low      Open    Volume  Daily Return
Symbol Date                                                                     
AAPL   2018-07-02  187.1800  187.300  183.4200  183.8200  17731343           NaN
       2018-07-03  183.9200  187.950  183.5400  187.7900  13954806     -0.017416
       2018-07-04  183.9200  183.920  183.9200  183.9200         0      0.000000
       2018-07-05  185.4000  186.410  184.2800  185.2600  16604247      0.008047
       2018-07-06  187.9700  188.434  185.2000  185.4200  17485245      0.013862
WMLP   2018-07-02    1.3700    1.520    1.3300    1.3700      9139           NaN
       2018-07-03    1.4000    1.690    1.3800    1.6900      8075      0.021898
       2018-07-04    1.4000    1.400    1.4000    1.4000         0      0.000000
       2018-07-05    1.6000    1.600    1.4124    1.4124     29383      0.142857
       2018-07-06    1.7095    1.770    1.5200    1.6000     42599      0.068437

像往常一样,可能有一个更优雅或更高性能的解决方案,但这对于合理的数据大小应该适用。