如何同时对两列数据应用相同lambda的Box-Cox变换
实现多列共用同一lambda的Box-Cox变换方案
报错原因
scipy.stats.boxcox默认仅接收一维数组输入用于计算最优变换参数lambda,不直接支持多维度输入共享lambda的场景,所以你传入二维数组会触发ValueError: Data must be 1-dimensional报错。
实现方法
方案1:计算联合对数似然找最优lambda(通用场景,推荐)
该方案假设两列为独立分布但共享变换参数lambda,通过最大化两列的联合对数似然值求解最优参数,适用于绝大多数多列变量变换场景。
完整可运行代码如下:
import pandas as pd from scipy import stats from scipy.optimize import fmin # 读取数据 df = pd.read_csv('https://raw.githubusercontent.com/BenjaminKay/berndt-econometrics/master/data/floppy_ver/CHAP4.DAT/COLE', sep='\t') target_cols = ['SPEED', 'CAP'] data = df[target_cols].values # 定义负联合对数似然函数,用于优化求解 def negative_joint_llf(lmbda): # 分别计算两列在当前lambda下的对数似然值,求和后取反 llf_col1 = stats.boxcox_llf(lmbda, data[:, 0]) llf_col2 = stats.boxcox_llf(lmbda, data[:, 1]) return -(llf_col1 + llf_col2) # 求解最优lambda,初始猜测值设为1,关闭优化过程输出 optimal_lmbda = fmin(negative_joint_llf, x0=1, disp=False)[0] print(f"计算得到的最优共同lambda:{optimal_lmbda:.4f}") # 用最优lambda分别对两列做变换 df['SPEED_boxcox'] = stats.boxcox(df['SPEED'], lmbda=optimal_lmbda) df['CAP_boxcox'] = stats.boxcox(df['CAP'], lmbda=optimal_lmbda)
方案2:展平数组求解(仅适合同分布场景)
如果你的两列数据服从同一个分布,可以直接把两列数据展平为一维数组,传入stats.boxcox求解最优lambda,再拆分回两列即可:
import pandas as pd from scipy import stats df = pd.read_csv('https://raw.githubusercontent.com/BenjaminKay/berndt-econometrics/master/data/floppy_ver/CHAP4.DAT/COLE', sep='\t') target_cols = ['SPEED', 'CAP'] # 展平为一维数组求解lambda flatten_data = df[target_cols].values.flatten() transformed_flatten, optimal_lmbda = stats.boxcox(flatten_data) # 拆分变换后的结果回两列 df[['SPEED_boxcox', 'CAP_boxcox']] = transformed_flatten.reshape(-1, 2)
注意事项
Box-Cox变换要求输入数据全部为正值,如果你的数据存在小于等于0的值,需要先做平移处理(比如所有值加上一个常数,使得最小值大于0)再执行变换。
内容的提问来源于stack exchange,提问作者Arturo Sbr
相关产品推荐
相关产品推荐

