Problem Setup & Goal

我有一个多索引Pandas DataFrame,它看起来像这样:

imp或t 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

Current W或k

我设法从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] f或 i1,i2 in df.index]]
print(df_masked.to_string())

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

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

Similar Problems/Solutions

我见过的类似问题不涉及多索引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())

另一种方法是创建一个新的多索引,将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相关问答推荐

为什么符号没有按顺序添加?

按顺序合并2个词典列表

如何在类和classy-fastapi -fastapi- followup中使用FastAPI创建路由

优化器的运行顺序影响PyTorch中的预测

Pandas DataFrame中行之间的差异

连接一个rabrame和另一个1d rabrame不是问题,但当使用[...]'运算符会产生不同的结果

Asyncio:如何从子进程中读取stdout?

mypy无法推断类型参数.List和Iterable的区别

如何使用SentenceTransformers创建矢量嵌入?

Pandas—堆栈多索引头,但不包括第一列

如何删除重复的文字翻拍?

裁剪数字.nd数组引发-ValueError:无法将空图像写入JPEG

如何使用pytest在traceback中找到特定的异常

Scipy差分进化:如何传递矩阵作为参数进行优化?

read_csv分隔符正在创建无关的空列

Regex用于匹配Python中逗号分隔的AWS区域

基于2级列表的Pandas 切片3级多索引

根据两个lambda条件筛选组并根据条件创建新列的最佳方式是什么?

使用loc计算特定行的平均值,loc找不到行值

滑动子数组美容工作在IDE上,但不是在leetcode上