在熊猫中创建层次结构列的问题

时间:2020-10-25 20:43:42

标签: pandas dataframe multi-index

只需接近熊猫中的层次列。原始数据帧(df)包含27列,如下所示(股票代码为索引):

        Report Date   Shares        Gross Profit      ...
Ticker                                                                          
AAPL    2010-07-31    347000000.0   543000000.0       ...     
AAPL    2010-10-31    344000000.0   548000000.0       ...
AAPL    2011-01-31    347000000.0   556000000.0       ...
AAPL    2011-04-30    347000000.0   580000000.0       ...
AAPL    2011-07-31    348000000.0   591000000.0       ...

我想修改列结构,以使第一级为报告日期,第二级为 Shares 毛利润强>。我尝试仅使用一个股票代码(AAPL)来创建具有此结构的新数据框,这是我使用的代码:

col = pd.MultiIndex.from_product([df['Report Date'], df[['Shares', 'Gross Profit']]])
df1 = pd.DataFrame(df.loc['AAPL'], columns=col)

似乎很有效,但是只有NaN:

Report Date 2010-07-31           2010-10-31               \
            Shares  Gross Profit Shares Gross Profit   
Ticker                                                                
AAPL        NaN     NaN          NaN          NaN   
AAPL        NaN     NaN          NaN          NaN   
AAPL        NaN     NaN          NaN          NaN   
AAPL        NaN     NaN          NaN          NaN   

此外,形状爆炸为(78,112668)。有人可以发现错误吗?我猜它在MultiIndex.from_product中,但是不知道在哪里。

1 个答案:

答案 0 :(得分:0)

解决方案

如果我们的目标是首先生成所需输出的转置版本,则可以用df.melt()解决此问题。您可以轻松地在MultiIndex之前设置双层df.transpose()

df_want = df.melt(id_vars="Report Date", value_vars=["Shares", "Gross Profit"])\
    .sort_values(["Report Date", "variable"])\
    .set_index(["Report Date", "variable"])\
    .transpose()

结果

print(df_want)

Report Date   2010-07-31               ...   2011-07-31             
variable    Gross Profit       Shares  ... Gross Profit       Shares
value        543000000.0  347000000.0  ...  591000000.0  348000000.0

[1 rows x 10 columns]

最初尝试的问题:IMO更好的数据处理策略是让所需的索引/列在数据处理管道中自然生成或通过标准Pandas API设置,尤其是源数据框中已经存在名称或索引/列时。

编辑:“自然产生所需的索引/列”表示不要在df.f1(...).f2(...).f3(...)...管道之外进行计算,而将外部生成的索引/列分配给输出DataFrame。一般而言,这种方法可以产生较少的错误且易于维护的代码。

换句话说,手动生成索引或列名不太可能是一种Pa​​ndastic的方法,除非可能是为空数据帧进行预分配。

通用到多个股票行情

我认为,一次处理多个报价器是一个现实的用例。因此,我也提供了这样一个通用版本,以防万一。当然,该解决方案也适用于单行情数据框。

数据

        Report Date   Shares        Gross Profit
Ticker                                                              
AAPL    2010-07-31    347000000.0   543000000.0   
AAPL    2010-10-31    344000000.0   548000000.0 
AAPL    2011-01-31    347000000.0   556000000.0 
AAPL    2011-04-30    347000000.0   580000000.0 
AAPL    2011-07-31    348000000.0   591000000.0
GOOG    2011-07-31    448000004.0   691000000.0 
GOOG    2010-07-31    447000004.0   643000000.0 
GOOG    2010-10-31    444000004.0   648000000.0 
GOOG    2011-01-31    447000004.0   656000000.0 
GOOG    2011-04-30    447000004.0   680000000.0 

代码

df_want = df.reset_index()\
    .melt(id_vars=["Ticker", "Report Date"], value_vars=["Shares", "Gross Profit"])\
    .sort_values(["Ticker", "Report Date", "variable"])\
    .pivot(index="Ticker", columns=["Report Date", "variable"], values="value")

结果

print(df_want)

Report Date   2010-07-31               ...   2011-07-31             
variable    Gross Profit       Shares  ... Gross Profit       Shares
Ticker                                 ...                          
AAPL         543000000.0  347000000.0  ...  591000000.0  348000000.0
GOOG         643000000.0  447000004.0  ...  691000000.0  448000004.0
[2 rows x 10 columns]

我在64位debian 10笔记本电脑上使用pandas v1.1.3和python 3.7。