在R中使用caret/recipes实现YeoJohnson变换遇问题求助
问题:如何让caret和recipes包对所有数值列执行YeoJohnson变换?
在使用caret和recipes包对spam数据集的数值列执行YeoJohnson变换时,出现仅部分变量被转换的情况,而bestNormalize和sklearn的PowerTransformer能正常转换所有列。以下是针对两个包的解决方法:
针对caret包的解决方法
caret的preProcess()函数中,YeoJohnson变换默认会通过Shapiro-Wilk检验判断变量是否需要变换,默认阈值thresh=0.9——当变量的Shapiro-Wilk检验p值大于0.9时,认为变量已足够接近正态分布,会跳过变换。要强制对所有数值列应用变换,只需将thresh设置为0:
library(tidyverse) library(tidytuesdayR) library(caret) spam <- tt_load(2023, week=33)$spam # 修改preProcess参数,强制所有变量执行YeoJohnson变换 pp_hpc <- caret::preProcess(spam[,1:6], method = c("center", "scale", "YeoJohnson"), thresh = 0) # 关键参数:设置阈值为0 # 查看预处理结果,此时所有6个变量都会被标记为Yeo-Johnson转换 pp_hpc # 应用变换 transformed <- predict(pp_hpc, newdata = spam[,1:6])
针对recipes包的解决方法
recipes的step_YeoJohnson()同样默认带有**threshold=0.9**的参数逻辑,即跳过正态性足够的变量。要强制转换所有数值列,只需在步骤中设置threshold=0:
library(recipes) # 定义配方(即使仅用于转换数据,此结构是合规的) rec <- recipe(yesno ~ ., data = spam) # 修改step_YeoJohnson参数,强制所有数值列变换 yj_transform <- step_YeoJohnson(rec, all_numeric(), threshold = 0) yj_estimates <- prep(yj_transform, verbose = T) # 查看训练后的配方,此时所有数值变量都会被标记为已执行Yeo-Johnson变换 yj_estimates # 应用变换 yj_te <- bake(yj_estimates, spam)
核心原因说明
caret和recipes的YeoJohnson实现默认加入了正态性检验的筛选逻辑,目的是避免对已经近似正态的变量做冗余变换。若需要强制转换所有数值列,只需将检验阈值设为0,跳过筛选逻辑即可。
内容的提问来源于stack exchange,提问作者Matias Andina
相关产品推荐
相关产品推荐

