如何基于目标列连续序列用均值替换特征列值?代码问题排查
问题描述
拥有时序数据,需根据target列中的连续序列,计算对应feature1、feature2列的均值,并用该均值替换序列内的特征值。例如表格中target列的连续3个1序列,要计算该序列feature1和feature2的均值,再替换对应行的特征值,且对每个target序列执行此操作。
示例数据
| ID | time(s) | feature1 | feature2 | target |
|---|---|---|---|---|
| abc | 500 | 2.56789 | 91.12834 | 0 |
| abc | 1000 | 2.45678 | 91.23452 | 1 |
| abc | 1500 | 2.36589 | 91.54398 | 1 |
| abc | 2000 | 2.56428 | 91.32348 | 1 |
| abc | 2500 | 2.25869 | 91.79322 | 0 |
| cba | 500 | 5.36589 | 93.54398 | 1 |
| cba | 1000 | 5.56428 | 93.32348 | 1 |
| cba | 1500 | 5.25869 | 94.79322 | 0 |
尝试的代码
def averaging(input_df: pd.DataFrame): output_df = input_df.copy() target_index = [] for _, sub_df in input_df.groupby('ID'): _index = sub_df.index _targets = sub_df['target'].tolist() before = 1 if _targets[0] == 1 else 0 tmp = [] if before: tmp.append(_index[0]) for i, flag in enumerate(_targets): if flag == 1 and before == 0: tmp.append(_index[i]) elif flag == 0 and before == 1: tmp.append(_index[i]) target_index.append(tmp) tmp = [] before = flag if tmp: tmp.append(_index[-1]+1) target_index.append(tmp) output_df['target_id'] = 0 for i, (indexi, indexj) in enumerate(target_index): output_df.iloc[indexi:indexj]['target_id'] = i+1 targetid2avg = output_df.loc[output_df['target_id']!=0].groupby('target_id')[['feature1', 'feature2']].mean() targetid2avg.columns = ['target_feature1', 'target_feature2'] output_df = output_df.merge(targetid2avg, on='target_id', how='left') output_df.loc[output_df['target_id']!=0, ['feature1', 'feature2']] = output_df.loc[output_df['target_id']!=0, ['target_feature1', 'target_feature2']].values output_df = output_df.drop(columns=['target_feature1', 'target_feature2'], axis=1) return output_df
遇到的问题
为output_df的target_id列赋值时,该列始终为0,无法正确标记序列。
问题分析与解决
原代码问题根源
赋值target_id时,output_df.iloc[indexi:indexj]['target_id'] = i+1属于链式索引,会创建DataFrame的切片副本而非直接修改原DataFrame,导致赋值操作仅作用在副本上,原DataFrame的target_id列未被更新。
修正后的代码
将链式索引改为直接定位列的赋值方式,避免副本问题:
def averaging(input_df: pd.DataFrame): output_df = input_df.copy() target_index = [] for _, sub_df in input_df.groupby('ID'): _index = sub_df.index _targets = sub_df['target'].tolist() before = 1 if _targets[0] == 1 else 0 tmp = [] if before: tmp.append(_index[0]) for i, flag in enumerate(_targets): if flag == 1 and before == 0: tmp.append(_index[i]) elif flag == 0 and before == 1: tmp.append(_index[i]) target_index.append(tmp) tmp = [] before = flag if tmp: tmp.append(_index[-1]+1) target_index.append(tmp) output_df['target_id'] = 0 target_col_idx = output_df.columns.get_loc('target_id') for i, (indexi, indexj) in enumerate(target_index): # 直接定位行和列,修改原DataFrame output_df.iloc[indexi:indexj, target_col_idx] = i+1 targetid2avg = output_df.loc[output_df['target_id']!=0].groupby('target_id')[['feature1', 'feature2']].mean() targetid2avg.columns = ['target_feature1', 'target_feature2'] output_df = output_df.merge(targetid2avg, on='target_id', how='left') output_df.loc[output_df['target_id']!=0, ['feature1', 'feature2']] = output_df.loc[output_df['target_id']!=0, ['target_feature1', 'target_feature2']].values output_df = output_df.drop(columns=['target_feature1', 'target_feature2'], axis=1) return output_df
更简洁的Pandas实现方案
利用Pandas分组功能,自动识别连续target=1序列,无需手动处理索引:
def averaging_simplified(input_df: pd.DataFrame): output_df = input_df.copy() # 按ID分组,生成连续target=1的序列标识 output_df['target_id'] = output_df.groupby('ID').apply( lambda x: (x['target'] == 1).cumsum() * x['target'] ).reset_index(level=0, drop=True) # 计算每个target_id对应的特征均值 avg_df = output_df[output_df['target_id'] != 0].groupby('target_id')[['feature1', 'feature2']].mean() # 替换对应序列的特征值 output_df = output_df.merge(avg_df, on='target_id', suffixes=('', '_avg'), how='left') output_df.loc[output_df['target_id'] != 0, ['feature1', 'feature2']] = output_df.loc[output_df['target_id'] != 0, ['feature1_avg', 'feature2_avg']].values # 清理临时列 output_df = output_df.drop(columns=['feature1_avg', 'feature2_avg']) return output_df
代码说明
- 生成
target_id时,(x['target'] == 1).cumsum()对连续的1序列累加计数,再乘以x['target']让非1的行保持0,自动完成序列标记。 - 后续均值计算和替换逻辑更简洁,避免手动处理索引的复杂操作,降低出错概率。
内容的提问来源于stack exchange,提问作者Ayo
相关产品推荐
相关产品推荐

