如何在Pandas中按ID组计算特征与组内label=1行的差值?
用Pandas实现按组转换特征值
解决思路
针对每个ID分组,先提取组内label=1行的特征作为基准值,再对组内label=0的行,用基准值减去该行特征值(或生成表达式字符串),label=1的行保持原特征不变。
代码实现
1. 构造示例数据
import pandas as pd # 构造示例DataFrame data = { 'ID': [1, 1, 2, 2], 'Feature_1': [10, 9, 100, 90], 'Feature_2': [3, 1, 30, 10], 'Feature_3': [4, 2, 40, 20], 'label': [1, 0, 1, 0] } df = pd.DataFrame(data)
2. 提取组内基准特征
# 提取每组label=1的特征值,按ID索引 base_features = df[df['label'] == 1].set_index('ID').drop('label', axis=1)
3. 合并基准特征与原数据
# 合并原数据和基准特征,添加后缀区分基准列 merged_df = df.merge(base_features, on='ID', suffixes=('', '_base'))
4. 按条件转换特征值
如果需要数值结果(如1而非10-9):
# 定义所有特征列 feature_cols = [col for col in df.columns if col.startswith('Feature_')] # 遍历特征列,对label=0的行计算基准值减当前值 for col in feature_cols: merged_df[col] = merged_df.apply( lambda row: row[f'{col}_base'] - row[col] if row['label'] == 0 else row[col], axis=1 ) # 清理临时基准列,得到最终结果 result_df = merged_df.drop([f'{col}_base' for col in feature_cols], axis=1)
如果需要表达式字符串(如10-9):
for col in feature_cols: merged_df[col] = merged_df.apply( lambda row: f"{row[f'{col}_base']}-{row[col]}" if row['label'] == 0 else row[col], axis=1 ) result_df = merged_df.drop([f'{col}_base' for col in feature_cols], axis=1)
5. 查看结果
print(result_df)
数值结果输出:
ID Feature_1 Feature_2 Feature_3 label 0 1 10 3 4 1 1 1 1 2 2 0 2 2 100 30 40 1 3 2 10 20 20 0
表达式字符串结果输出:
ID Feature_1 Feature_2 Feature_3 label 0 1 10 3 4 1 1 1 10-9 3-1 4-2 0 2 2 100 30 40 1 3 2 100-90 30-10 40-20 0
关键说明
- 利用
merge将每组的基准值关联到所有行,避免循环分组操作,提升效率。 - 通过
apply结合条件判断,精准控制仅修改label=0的行。 - 特征列通过前缀自动识别,无需硬编码列名,适配更多特征的场景。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

