1

刚刚接近熊猫中的分层列。原始数据框 (df) 有 27 列,如下所示(Ticker 是索引):

        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       ...

我想修改列结构,使第一级是Report Date,第二级是列SharesGross Profit。我试图为一个股票代码(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 但不明白在哪里。

4

1 回答 1

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。通常,这种方法可以生成不易出错且更易于维护的代码。

换句话说,手动生成索引或列名不太可能是 Pandastic 的方式,除了可能用于空数据帧的预分配。

泛化到多个代码

我认为一次处理多个代码很可能是一个现实的用例。所以我也提供这样一个通用的版本以防万一。该解决方案当然也适用于单代码数据帧。

数据

        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。

于 2020-10-25T21:38:37.850 回答