如何提取Pandas MultiIndex中同时含指定property的ID?
问题描述
我有如下结构的数据集:
import pandas as pd # Create individual pandas DataFrame. df1 = pd.DataFrame({'Col1': [1, 2, 3, 4], 'Col2': [99, 98, 95, 90]}, index=['A', 'B', 'C', 'D']) df2 = pd.DataFrame({'Col1': [1, 2], 'Col2': [99, 98]}, index=['A', 'B']) df3 = pd.DataFrame({'Col1': [3, 4], 'Col2': [95, 90]}, index=['C', 'D']) df4 = pd.DataFrame({'Col1': [3, 4], 'Col2': [95, 90]}, index=['B', 'C']) # Combine into one multi-index dataframe df_dict = dict(obj1=df1, obj2=df2, obj3=df3, obj4=df4) # Assign multi-index labels mDF = pd.concat(list(df_dict.values()), keys=list(df_dict.keys())) mDF.rename_axis(index=["ID", "property"], inplace=True) print(mDF, '\n')
生成的MultiIndex DataFrame如下:
Col1 Col2 ID property obj1 A 1 99 B 2 98 C 3 95 D 4 90 obj2 A 1 99 B 2 98 obj3 C 3 95 D 4 90 obj4 B 3 95 C 4 90
我的需求是:计算所有ID中property为A和B的Col1值之和,但仅针对同时包含A和B两个property的ID(即obj1和obj2)。
我尝试用isin和query方法筛选:
idcs_isin = mDF.index.get_level_values('property').isin(['A', 'B']) idcs_query = mDF.query('property in ["A","B"]') print(f'isin:\n{mDF.loc[idcs_isin]}\n') print(f'Query:\n{idcs_query}')
但结果返回了包含任一指定property的ID(比如obj4只包含B也被纳入):
isin: Col1 Col2 ID property obj1 A 1 99 B 2 98 obj2 A 1 99 B 2 98 obj4 B 3 95 Query: Col1 Col2 ID property obj1 A 1 99 B 2 98 obj2 A 1 99 B 2 98 obj4 B 3 95
请问如何提取仅同时包含A和B两个property的ID?
解决方案
方法一:分组后检查属性集合
先筛选出目标property的行,再按ID分组,检查每个分组是否同时包含A和B:
# 筛选出property为A或B的行并按ID分组 target_groups = mDF[mDF.index.get_level_values('property').isin(['A', 'B'])].groupby('ID') # 收集同时包含A和B的ID valid_ids = [id for id, group in target_groups if {'A', 'B'}.issubset(group.index.get_level_values('property'))] # 提取符合条件的数据并计算Col1之和 filtered_data = mDF.loc[valid_ids].query('property in ["A", "B"]') col1_sum = filtered_data.groupby('ID')['Col1'].sum() print(col1_sum)
输出结果:
ID obj1 3 obj2 3 Name: Col1, dtype: int64
方法二:简洁的分组判断
通过重置索引后分组,直接判断每个ID的属性集合是否包含A和B:
# 判断每个ID是否同时包含A和B has_both_properties = mDF.reset_index().groupby('ID')['property'].apply(lambda x: {'A', 'B'}.issubset(x)) # 获取有效ID列表 valid_ids = has_both_properties[has_both_properties].index # 计算目标Col1之和 col1_sum = mDF.loc[valid_ids].query('property in ["A", "B"]')['Col1'].groupby('ID').sum() print(col1_sum)
方法说明
两种方法核心都是先筛选出同时具备A和B属性的ID,再基于这些ID提取对应数据计算总和:
- 利用集合的
issubset方法可以直接判断分组内的属性是否包含目标集合,逻辑清晰直观。 - 避免了直接筛选属性带来的“包含任一即保留”的问题,精准锁定同时满足两个条件的ID。
内容的提问来源于stack exchange,提问作者Delosari
相关产品推荐
相关产品推荐

