Pandas groupby 使用多索引为数据帧产生意外结果

问题描述 投票:0回答:1

我有一个

pandas.DataFrame
,其 Multiindex 有 3 个级别。我想按前两个级别进行分组,并将最大值保留在第三个级别。
pandas.groupby
产生意想不到的结果。我想知道是什么原因。我应该在这里添加任何参数吗?

idxslc = pd.IndexSlice

def keep_latest_info(df):
    print('Before:')
    print(df)
    if len(df) == 1:
       return df

    max_dt = df.index.get_level_values(-1).max()
    df = df.loc[idxslc[:, :, max_dt]]
    print('After:' )
    print(df)
    return df 

df = pd.DataFrame(np.array(((1, 2, 2), (4, 9, 9), (5, 6, 7), (3, 9, 1)))).T.set_index([0, 1, 2])
df.index = df.index.rename('a-b-c'.split('-'))
df.groupby(level=[0, 1], group_keys=True, as_index=True).apply(keep_latest_info)

结果如下。可以看出,第二组(第2行和第3行)的输出不再具有3级索引。这是为什么?

Before:
       3
a b c   
1 4 5  3
Before:
       3
a b c   
2 9 6  9
    7  1
After:
     3
a b   
2 9  1


AssertionError: Cannot concat indices that do not have the same number of levels
python-3.x pandas group-by
1个回答
0
投票

这是由于 keep_latest_info 函数中如何执行切片所致。当您使用 df.loc[idxslc[:, :, max_dt]] 对 DataFrame 进行切片时,它会修改索引级别,在这种情况下会删除第三个级别。

要解决此问题,您需要在整个函数中维护 MultiIndex 结构。您可以通过修改 keep_latest_info 函数来实现此目的,如下所示:

import pandas as pd
import numpy as np

idxslc = pd.IndexSlice

def keep_latest_info(df):
    print('Before:')
    print(df)
    
    if len(df) == 1:
       return df

    max_dt = df.index.get_level_values(-1).max()
    df = df.loc[idxslc[:,:,max_dt], :]
    print('After:')
    print(df)
    return df 

df = pd.DataFrame(np.array(((1, 2, 2), (4, 9, 9), (5, 6, 7), (3, 9, 1)))).T.set_index([0, 1, 2])
df.index = df.index.rename('a-b-c'.split('-'))

result = df.groupby(level=[0, 1], group_keys=True, as_index=False).apply(keep_latest_info)

所做的更改:

  1. 在 idxslc[:,:,max_dt] 之后添加 [:, :] 以维护 MultiIndex 的所有级别。 陈
  2. 在 groupby 函数调用中将 as_index=True 更改为 as_index=False,以将索引保留为结果 DataFrame 中的列。 通过这些更改,该函数将在整个操作过程中保留 MultiIndex 结构,并且您应该获得预期的输出,没有任何错误。
© www.soinside.com 2019 - 2024. All rights reserved.