如何检查Pandas分组中指定列是否包含全部预定义值
问题描述
我有一个DataFrame,需要按Patient ID分组,检查每个分组的Inclusion列是否包含全部6个必填值:-3、-2、-1、1、2、3。符合条件的分组所有行标记为Y,否则标记为N。尝试用transform结合lambda和all的方式实现,但没能成功。
原始DataFrame:
| Patient ID | Surg ID | Surg Type | Surg Date | Medical Appt Date | Inclusion |
|---|---|---|---|---|---|
| 1 | 1 | X | 2022-09-03 | 2022-03-04 | -3 |
| 1 | 1 | X | 2022-09-03 | 2022-05-04 | -2 |
| 1 | 1 | X | 2022-09-03 | 2022-06-04 | -1 |
| 1 | 1 | X | 2022-09-03 | 2022-11-04 | 1 |
| 1 | 1 | X | 2022-09-03 | 2022-11-29 | 2 |
| 1 | 1 | X | 2022-09-03 | 2023-01-02 | 3 |
| 2 | 1 | X | 2022-10-03 | 2022-09-01 | -2 |
| 2 | 1 | X | 2022-10-03 | 2022-09-11 | -1 |
| 2 | 1 | X | 2022-10-03 | 2022-10-12 | 1 |
| 2 | 1 | X | 2022-10-03 | 2022-10-29 | 2 |
| 2 | 1 | X | 2022-10-03 | 2022-12-12 | 3 |
期望得到的DataFrame:
| Patient ID | Surg ID | Surg Type | Surg Date | Medical Appt Date | Inclusion | IncludeYN |
|---|---|---|---|---|---|---|
| 1 | 1 | X | 2022-09-03 | 2022-03-04 | -3 | Y |
| 1 | 1 | X | 2022-09-03 | 2022-05-04 | -2 | Y |
| 1 | 1 | X | 2022-09-03 | 2022-06-04 | -1 | Y |
| 1 | 1 | X | 2022-09-03 | 2022-11-04 | 1 | Y |
| 1 | 1 | X | 2022-09-03 | 2022-11-29 | 2 | Y |
| 1 | 1 | X | 2022-09-03 | 2023-01-02 | 3 | Y |
| 2 | 1 | X | 2022-10-03 | 2022-09-01 | -2 | N |
| 2 | 1 | X | 2022-10-03 | 2022-09-11 | -1 | N |
| 2 | 1 | X | 2022-10-03 | 2022-10-12 | 1 | N |
| 2 | 1 | X | 2022-10-03 | 2022-10-29 | 2 | N |
| 2 | 1 | X | 2022-10-03 | 2022-12-12 | 3 | N |
解决方案
之前的实现失败是因为逻辑方向错误——若检查分组内每个值是否属于必填列表,无法确保必填列表的所有值都存在。正确逻辑是验证必填列表的所有值是否都包含在分组的Inclusion列中,以下两种方法均可实现需求:
方法一:集合比较法(效率更高)
利用集合的issubset方法快速判断必填值是否全部存在,再通过transform将结果广播到分组的每一行:
import pandas as pd # 定义必填值集合 required_values = {-3, -2, -1, 1, 2, 3} # 生成示例数据(替换为你的实际DataFrame) df = pd.DataFrame({ 'Patient ID': [1]*6 + [2]*5, 'Surg ID': [1]*11, 'Surg Type': ['X']*11, 'Surg Date': ['2022-09-03']*6 + ['2022-10-03']*5, 'Medical Appt Date': ['2022-03-04', '2022-05-04', '2022-06-04', '2022-11-04', '2022-11-29', '2023-01-02', '2022-09-01', '2022-09-11', '2022-10-12', '2022-10-29', '2022-12-12'], 'Inclusion': [-3, -2, -1, 1, 2, 3, -2, -1, 1, 2, 3] }) # 添加IncludeYN列 df['IncludeYN'] = df.groupby('Patient ID')['Inclusion'].transform( lambda x: 'Y' if required_values.issubset(set(x)) else 'N' )
方法二:isin+all组合法
遍历每个必填值,检查是否存在于分组中,再用all判断全部满足:
required_values = [-3, -2, -1, 1, 2, 3] df['IncludeYN'] = df.groupby('Patient ID')['Inclusion'].transform( lambda x: 'Y' if all(val in x.values for val in required_values) else 'N' )
两种方法均能输出你期望的结果,其中集合比较法在数据量较大时性能更优。
内容的提问来源于stack exchange,提问作者Eoin Vaughan
相关产品推荐
相关产品推荐

