python - 如何聚合行的子集并附加到 MultiIndexed Pandas DataFrame?

标签 python pandas dataframe multi-index

问题设置和目标

我有一个多索引的 Pandas DataFrame,如下所示:

import pandas as pd

df = pd.DataFrame({
    'Values':[1, 3, 4, 8, 5, 2, 9, 0, 2],
    'A':['A1', 'A1', 'A1', 'A1', 'A2', 'A2', 'A3', 'A3', 'A3'],
    'B':['foo', 'bar', 'fab', 'baz', 'foo', 'baz', 'qux', 'baz', 'bar']
})
df.set_index(['A','B'], inplace=True)
print(df.to_string())

        Values
A  B          
A1 foo       1
   bar       3
   fab       4
   baz       8
A2 foo       5
   baz       2
A3 qux       9
   baz       0
   bar       2

我的最终目标是以最简单、最规范的 Pandas 方式将 B 列中的所有“bar”和“baz”行替换为一个名为“other”(见下文)的汇总行。

       Values
A  B          
A1 foo       1
   fab       4
   other    11
A2 foo       5
   other     2
A3 qux       9
   other     2

目前的工作

我设法从 a similar problem 弄清楚如何为 MultiIndex DataFrame 创建掩码突出显示我们最终要聚合的行,这些行位于 agg_list 中。

agg_list = ['bar', 'baz']
# Create a mask that highlights the rows in B that are in agg_list
filterFunc = lambda x: x.index.get_level_values('B') in agg_list
mask = df.groupby(level=['A','B']).apply(filterFunc)

这会产生预期的掩码:

print(mask.to_string())

A   B  
A1  bar     True
    baz     True
    fab    False
    foo    False
A2  baz     True
    foo    False
A3  bar     True
    baz     True
    qux    False

而且我知道如何删除不再需要的行:

# Remove rows in B col that are in agg_list using mask
df_masked = df[[~mask.loc[i1, i2] for i1,i2 in df.index]]
print(df_masked.to_string())

    Values
A  B          
A1 foo       1
   fab       4
A2 foo       5
A3 qux       9

但我不知道如何对这些行进行实际的聚合/求和并将其附加到每个多索引行。

类似问题/解决方案

我见过的类似问题不涉及 Multiindex DataFrame,因此我不能完全使用某些解决方案,例如 this one ,它具有创建掩码然后附加汇总行的相同总体思路:

threshold = 6
m = df['value'] < threshold
df1 = df[~m].copy()
df1.loc['Z'] = df.loc[m, 'value'].sum()

m = df['value'] < threshold
df1 = df[~m].append(df.loc[m, ['value']].sum().rename('Z'))

最佳答案

这是一种为 B 重置索引、执行替换并聚合值的方法。

agg_list = ['bar', 'baz']
(df.reset_index(level=1)
.replace({'B':{'|'.join(agg_list):'other'}},regex=True)
.groupby(['A','B']).sum())

另一种方法是创建一个新的 MultiIndex,将 barbaz 替换为 other

(df.set_axis(pd.MultiIndex.from_arrays([df.index.get_level_values(0),
df.index.get_level_values(1).str.replace('|'.join(agg_list),'other')]))
.groupby(level=[0,1]).sum())

输出:

          Values
A  B            
A1 fab         4
   foo         1
   other      11
A2 foo         5
   other       2
A3 other       2
   qux         9

关于python - 如何聚合行的子集并附加到 MultiIndexed Pandas DataFrame?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73228173/

相关文章:

python - python中拉丁字符的特殊文本

python - 如何在 Python 中合并字典中的所有数据框

python - 将 'filepath' 列添加到 pandas DataFrame

python - 在这种情况下,为什么 read_csv skiprows 值需要低于应有的值?

r cumsum-like 函数,用于分割数据帧

Python多索引: Changing second level of index names

python - 创建一个函数来仅使用 numpy 计算二维矩阵中行向量的所有成对余弦相似度

python - SciPy 中 10j 的值是多少?

python - 从文件生成 block

python - 查找一行下一行