Pandas按分组批量缩放多列并实现逆变换的问题求助
解决多分组MinMaxScaler缩放后逆变换错误的问题
你遇到的问题核心是共用了同一个MinMaxScaler实例处理不同分组:当处理第二个分组(Customer B)时,scaler会重新拟合B的数据,直接覆盖掉之前拟合Customer A的参数,导致逆变换Customer A时用的是B的缩放规则,结果自然出错。
下面是完整的解决方案,我们会为每个分组单独创建并保存对应的Scaler实例,确保缩放和逆变换都使用对应分组的规则:
步骤1:还原原始数据结构
先把你的数据恢复成初始的DataFrame结构(如果之前修改过列名的话):
import pandas as pd from sklearn.preprocessing import MinMaxScaler # 构建原始数据 data = { ('X_data', 'Customer'): ['A']*5 + ['B']*7, ('X_data', '0'): [855.0, 989.0, 454.0, 574.0, 395.0, 875.0, 999.0, 434.0, 564.0, 345.0, 798.0, 815.0], ('X_data', '1'): [989.0, 454.0, 574.0, 395.0, 162.0, 999.0, 434.0, 564.0, 345.0, 798.0, 815.0, 929.0], ('X_data', '2'): [454.0, 574.0, 395.0, 162.0, 123.0, 434.0, 564.0, 345.0, 798.0, 815.0, 929.0, 444.0], ('X_data', '3'): [574.0, 395.0, 162.0, 123.0, 342.0, 564.0, 345.0, 798.0, 815.0, 929.0, 444.0, 554.0], ('y_data', 'Customer'): ['A']*5 + ['B']*7, ('y_data', '0'): [395.0, 162.0, 123.0, 342.0, 232.0, 345.0, 798.0, 815.0, 929.0, 444.0, 554.0, 395.0], ('y_data', '1'): [162.0, 123.0, 342.0, 232.0, 657.0, 798.0, 815.0, 929.0, 444.0, 554.0, 395.0, 768.0] } df = pd.DataFrame(data) X_data = df['X_data'] y_data = df['y_data']
步骤2:为每个分组单独训练并保存Scaler
用字典存储每个Customer对应的Scaler实例,分别处理X_data和y_data的所有数值列:
# 存储X_data各分组的Scaler x_scalers = {} scaled_X = X_data.copy() x_num_cols = scaled_X.columns.drop('Customer') # 排除Customer列,只处理数值列 for customer, group in scaled_X.groupby('Customer'): scaler = MinMaxScaler() # 拟合当前分组并完成缩放 scaled_values = scaler.fit_transform(group[x_num_cols]) scaled_X.loc[group.index, x_num_cols] = scaled_values # 保存当前分组的Scaler,用于后续逆变换 x_scalers[customer] = scaler # 同理处理y_data y_scalers = {} scaled_y = y_data.copy() y_num_cols = scaled_y.columns.drop('Customer') for customer, group in scaled_y.groupby('Customer'): scaler = MinMaxScaler() scaled_values = scaler.fit_transform(group[y_num_cols]) scaled_y.loc[group.index, y_num_cols] = scaled_values y_scalers[customer] = scaler
步骤3:用对应Scaler完成逆变换
现在调用每个分组专属的Scaler进行逆变换,就能得到准确的原始数据:
# 逆变换X_data inv_X = scaled_X.copy() for customer, group in inv_X.groupby('Customer'): scaler = x_scalers[customer] inv_values = scaler.inverse_transform(group[x_num_cols]) inv_X.loc[group.index, x_num_cols] = inv_values # 逆变换y_data inv_y = scaled_y.copy() for customer, group in inv_y.groupby('Customer'): scaler = y_scalers[customer] inv_values = scaler.inverse_transform(group[y_num_cols]) inv_y.loc[group.index, y_num_cols] = inv_values # 验证结果(和原始数据完全一致) print("X_data逆变换结果:") print(inv_X.round(2)) print("\ny_data逆变换结果:") print(inv_y.round(2))
你的原始代码出错原因
在你原来的代码里,x_scaler是一个全局实例:
- 处理Customer A时,
x_scaler拟合了A的0列数据 - 处理Customer B时,
x_scaler会重新拟合B的0列数据,直接覆盖了A的拟合参数 - 逆变换时,
x_scaler已经是拟合B后的状态,所以逆变换A的数据时用的是B的min/max,结果自然错误
而上面的方案为每个分组单独创建Scaler,彻底避免了参数被覆盖的问题,确保每个分组的缩放和逆变换都使用自己的规则。
内容的提问来源于stack exchange,提问作者mukesh tech01
相关产品推荐
相关产品推荐

