我有一个
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
这是由于 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)
所做的更改: