前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >tidymodels菜谱:数据预处理

tidymodels菜谱:数据预处理

作者头像
医学和生信笔记
发布2023-08-30 12:03:39
1740
发布2023-08-30 12:03:39
举报

在前面的推文中我们介绍了数据预处理的重要性以及演示了caret包中的数据预处理方法:

一定要先看上两篇推文,因为一些方法解释和原理都在前面解释过

今天列举常见的数据预处理方法,使用recipes包。这个包是tidymodels的一部分,专门用于数据预处理,是非常重要的一个部分,并且也包含部分特征选择的函数。

本文将会介绍recipes的基本用法以及一些常用的数据预处理方法实现。

recipes的使用其实很简单,但是由于数据预处理步骤非常多,难以记住,所以我把一些常用的recipes的预处理函数列在这里,方便大家选择。

主要包括以下几个部分内容:

  • 缺失值插补
  • 作用于单个预测变量
  • 离散化
  • 哑变量和编码
  • 交互项
  • 中心化标准化
  • 作用于多个预测变量
  • 移除预测变量
  • 样本(行)选择
  • 其他

加载R包

代码语言:javascript
复制
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.4.1     ✔ purrr   1.0.1
## ✔ tibble  3.2.1     ✔ dplyr   1.1.1
## ✔ tidyr   1.3.0     ✔ stringr 1.5.0
## ✔ readr   2.1.4     ✔ forcats 1.0.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(tidymodels)
## ── Attaching packages ────────────────────────────────────── tidymodels 1.0.0 ──
## ✔ broom        1.0.3     ✔ rsample      1.1.1
## ✔ dials        1.1.0     ✔ tune         1.0.1
## ✔ infer        1.0.4     ✔ workflows    1.1.2
## ✔ modeldata    1.1.0     ✔ workflowsets 1.0.0
## ✔ parsnip      1.0.3     ✔ yardstick    1.1.0
## ✔ recipes      1.0.4     
## ── Conflicts ───────────────────────────────────────── tidymodels_conflicts() ──
## ✖ scales::discard() masks purrr::discard()
## ✖ dplyr::filter()   masks stats::filter()
## ✖ recipes::fixed()  masks stringr::fixed()
## ✖ dplyr::lag()      masks stats::lag()
## ✖ yardstick::spec() masks readr::spec()
## ✖ recipes::step()   masks stats::step()
## • Use suppressPackageStartupMessages() to eliminate package startup messages
tidymodels_prefer()

使用之前用过的segmentationOriginal数据:

代码语言:javascript
复制
library(AppliedPredictiveModeling)
library(caret)
## Loading required package: lattice

data("segmentationOriginal")

segData <- subset(segmentationOriginal, Case == "Train")
cellID <- segData$Cell
class <- segData$Class
case <- segData$Case
#segData <- segData[ ,  -(1:3)]
statusColNum <- grep("Status", names(segData))
statusColNum
##  [1]   5   7  12  13  14  15  17  19  23  24  25  29  30  31  33  35  37  39  41
## [20]  43  46  47  49  51  54  55  58  59  62  63  66  67  71  72  73  75  76  77
## [39]  79  81  83  85  87  89  91  95  96  97 100 101 106 107 108 109 113 114 115
## [58] 117
segData <- segData[ , -statusColNum]

segData <- segData[,-(1:2)]

dim(segData) # 使用的演示数据
## [1] 1009   59

中心化和标准化

1个函数同时完成中心化和标准化:

代码语言:javascript
复制
step_normalize()

也有分开版本:

代码语言:javascript
复制
# 选择数据预处理步骤

# 首先第一步是建立recipe
rec <- recipe(Class ~ ., data = segData)

# 然后一步一步地添加你想要的预处理步骤
preproc <- rec %>% 
  step_center(XCentroid,YCentroid) %>% # 中心化
  step_scale(XCentroid,YCentroid) %>% # 标准化
  prep()

preproc
## Recipe
## 
## Inputs:
## 
##       role #variables
##    outcome          1
##  predictor         58
## 
## Training data contained 1009 data points and no missing data.
## 
## Operations:
## 
## Centering for XCentroid, YCentroid [trained]
## Scaling for XCentroid, YCentroid [trained]

注意上面数据预处理步骤的写法,第一步是建立recipe,然后是选择预处理步骤,在recipes中,所有的数据预处理步骤都是以step_xxx这种形式出现的;

然后是预处理应用于哪些变量,可以直接写变量名字,和dplyr中一模一样的方法,所以也支持tidyselect包的各种用法,比如contains()/starts_with()/ends_with()/matches()/num_range()等,这种写法。

除此之外,还支持recipes的一些简便操作。由于数据预处理一般是作用于预测变量,有的是数值型,有的是分类变量,所以tidymodels开发了一些好用的函数,用于快速选择变量。主要是以下几个:

代码语言:javascript
复制
# 官网这部分更新很快,可以到官网查看最新的,这里只是一些常用的
all_numeric()
all_integer()
all_double()
all_nominal()
all_ordered()
all_unordered()
all_factor()
all_string()
all_date()
all_datetime()
all_numeric_predictors()
all_nominal_predictors()
all_predictors()
all_outcomes()

看名字就知道,是用来选择不同类型的变量的,使用方法也很简单:

代码语言:javascript
复制
recipe(HHV ~ ., data = biomass) %>%
  step_center(all_numeric_predictors()) # 把中心化应用于 "所有的数值型预测变量"

是不是很方便呢?

如果你想把数据预处理步骤应用于数据,记得最后一定要加上prep(),然后使用bake()函数执行预处理步骤:

代码语言:javascript
复制
segdata_scaled <- bake(preproc, new_data = NULL) 
glimpse(segdata_scaled)
## Rows: 1,009
## Columns: 59
## $ AngleCh1                <dbl> 133.75204, 106.64639, 69.15032, 109.41643, 104…
## $ AreaCh1                 <int> 819, 431, 298, 256, 258, 358, 158, 315, 246, 2…
## $ AvgIntenCh1             <dbl> 31.92327, 28.03883, 19.45614, 18.82857, 17.570…
## $ AvgIntenCh2             <dbl> 205.878517, 115.315534, 101.294737, 125.938776…
## $ AvgIntenCh3             <dbl> 69.91688, 63.94175, 28.21754, 13.60000, 22.461…
## $ AvgIntenCh4             <dbl> 164.15345, 106.69660, 31.02807, 46.80000, 71.2…
## $ ConvexHullAreaRatioCh1  <dbl> 1.263158, 1.053310, 1.202625, 1.081871, 1.0757…
## $ ConvexHullPerimRatioCh1 <dbl> 0.7970801, 0.9354750, 0.8658291, 0.9204595, 0.…
## $ DiffIntenDensityCh1     <dbl> 31.87500, 32.48771, 26.73228, 28.02004, 27.876…
## $ DiffIntenDensityCh3     <dbl> 43.12228, 35.98577, 22.91732, 14.87082, 16.119…
## $ DiffIntenDensityCh4     <dbl> 79.30842, 51.35705, 26.39370, 32.69710, 36.185…
## $ EntropyIntenCh1         <dbl> 6.087592, 5.883557, 5.420065, 5.383272, 5.1842…
## $ EntropyIntenCh3         <dbl> 6.642761, 6.683000, 5.436732, 4.151183, 5.4862…
## $ EntropyIntenCh4         <dbl> 7.880155, 7.144601, 5.778329, 6.194035, 6.6246…
## $ EqCircDiamCh1           <dbl> 32.30558, 23.44892, 19.50279, 18.08245, 18.156…
## $ EqEllipseLWRCh1         <dbl> 1.558394, 1.375386, 3.391220, 1.378748, 1.6160…
## $ EqEllipseOblateVolCh1   <dbl> 2232.9055, 802.1945, 724.7143, 368.3097, 403.6…
## $ EqEllipseProlateVolCh1  <dbl> 1432.8246, 583.2504, 213.7031, 267.1334, 249.7…
## $ EqSphereAreaCh1         <dbl> 3278.7256, 1727.4104, 1194.9320, 1027.2222, 10…
## $ EqSphereVolCh1          <dbl> 17653.525, 6750.985, 3884.084, 3095.782, 3133.…
## $ FiberAlign2Ch3          <dbl> 0.48793541, 0.30052198, 0.22042390, 0.36423599…
## $ FiberAlign2Ch4          <dbl> 0.35237425, 0.52231582, 0.73325044, 0.48086857…
## $ FiberLengthCh1          <dbl> 64.28230, 21.14115, 43.14112, 22.29743, 26.528…
## $ FiberWidthCh1           <dbl> 13.167079, 21.141150, 7.404412, 12.057876, 10.…
## $ IntenCoocASMCh3         <dbl> 0.028051061, 0.006862315, 0.030962071, 0.10816…
## $ IntenCoocASMCh4         <dbl> 0.012594975, 0.006141691, 0.011033195, 0.00995…
## $ IntenCoocContrastCh3    <dbl> 8.2279529, 14.4460738, 7.2994574, 6.1605846, 9…
## $ IntenCoocContrastCh4    <dbl> 6.984046, 16.700843, 13.390884, 10.590685, 10.…
## $ IntenCoocEntropyCh3     <dbl> 6.822138, 7.580100, 6.312641, 5.044067, 6.9574…
## $ IntenCoocEntropyCh4     <dbl> 7.098988, 7.671478, 7.197026, 7.126900, 7.1447…
## $ IntenCoocMaxCh3         <dbl> 0.15321477, 0.02835052, 0.16279070, 0.31531532…
## $ IntenCoocMaxCh4         <dbl> 0.07387141, 0.02319588, 0.07751938, 0.05855856…
## $ KurtIntenCh1            <dbl> -0.24876907, -0.29348463, 0.62585612, -0.36469…
## $ KurtIntenCh3            <dbl> -0.3307839, 1.0512813, 0.1277406, 1.0833329, -…
## $ KurtIntenCh4            <dbl> -0.2652638, 0.1506140, -0.3472936, -0.6262704,…
## $ LengthCh1               <dbl> 47.21855, 28.14303, 37.85957, 23.05547, 26.319…
## $ NeighborAvgDistCh1      <dbl> 174.4442, 158.4774, 206.3344, 263.6345, 231.15…
## $ NeighborMinDistCh1      <dbl> 30.11114, 34.94477, 33.08030, 38.43038, 29.848…
## $ NeighborVarDistCh1      <dbl> 81.38063, 90.43768, 116.89276, 88.50411, 103.4…
## $ PerimCh1                <dbl> 154.89876, 84.56460, 101.09107, 68.71062, 73.4…
## $ ShapeBFRCh1             <dbl> 0.5397584, 0.7243116, 0.5891625, 0.6347914, 0.…
## $ ShapeLWRCh1             <dbl> 1.468181, 1.328408, 2.826854, 1.313937, 1.4903…
## $ ShapeP2ACh1             <dbl> 2.255810, 1.272193, 2.545840, 1.397364, 1.5886…
## $ SkewIntenCh1            <dbl> 0.39870467, 0.47248709, 0.88167138, 0.54673722…
## $ SkewIntenCh3            <dbl> 0.6197308, 0.9713788, 0.9998928, 1.4323632, 0.…
## $ SkewIntenCh4            <dbl> 0.52726313, 0.32470650, 0.60443988, 0.70380065…
## $ SpotFiberCountCh3       <int> 4, 2, 4, 0, 1, 1, 4, 2, 2, 2, 6, 4, 0, 1, 4, 2…
## $ SpotFiberCountCh4       <int> 11, 6, 7, 5, 4, 5, 4, 2, 5, 1, 10, 3, 2, 7, 6,…
## $ TotalIntenCh1           <int> 24964, 11552, 5545, 4613, 4340, 14461, 4743, 8…
## $ TotalIntenCh2           <int> 160997, 47510, 28869, 30855, 30719, 74259, 154…
## $ TotalIntenCh3           <int> 54675, 26344, 8042, 3332, 5548, 14474, 6265, 5…
## $ TotalIntenCh4           <int> 128368, 43959, 8843, 11466, 17588, 23099, 1753…
## $ VarIntenCh1             <dbl> 18.80923, 17.29564, 13.81897, 13.92294, 12.324…
## $ VarIntenCh3             <dbl> 56.71535, 37.67105, 30.00564, 18.64303, 17.747…
## $ VarIntenCh4             <dbl> 118.38814, 49.47052, 24.74954, 40.33175, 41.92…
## $ WidthCh1                <dbl> 32.16126, 21.18553, 13.39283, 17.54686, 17.660…
## $ XCentroid               <dbl> -0.367797851, 0.752354868, 1.585288942, -0.396…
## $ YCentroid               <dbl> 1.5684377, 0.6831217, 1.0838436, 2.9476668, 0.…
## $ Class                   <fct> PS, WS, PS, WS, PS, PS, PS, WS, WS, WS, WS, PS…

通过这个例子我们也可以发现recipes的基本用法,这个包主要就是用于数据预处理,所有的数据预处理步骤都是step_xxx这种形式,第一步都是以recipe()函数开头,建立你的“菜谱”,里面写上你的formuladata,然后通过管道符不断连接新的数据预处理方法,最后以prep()结尾,接着使用bake()函数,执行这些数据预处理步骤。

就像做饭一样,一步一步来,这也是这个包为什么叫recipes的原因!

去除偏度

通过psych包查看:

代码语言:javascript
复制
psych::skew(segData$AreaCh1) # 偏度
## [1] 3.525107
psych::kurtosi(segData$AreaCh1) # 峰度
## [1] 19.04179

画图查看:

代码语言:javascript
复制
ggplot(segData, aes(x = AreaCh1))+
  geom_histogram(bins = 10)

plot of chunk unnamed-chunk-9

以下是recipes中一些可以改善数据偏度的预处理函数:

代码语言:javascript
复制
step_inverse() 
step_log()
step_logit()
step_invlogit()
step_sqrt()
step_YeoJohnson()

演示下Boxcox变换:

代码语言:javascript
复制
preproc <- rec %>% 
  step_center(XCentroid,YCentroid) %>% 
  step_scale(XCentroid,YCentroid) %>% 
  step_BoxCox(AreaCh1) %>% 
  prep()

preproc
## Recipe
## 
## Inputs:
## 
##       role #variables
##    outcome          1
##  predictor         58
## 
## Training data contained 1009 data points and no missing data.
## 
## Operations:
## 
## Centering for XCentroid, YCentroid [trained]
## Scaling for XCentroid, YCentroid [trained]
## Box-Cox transformation on AreaCh1 [trained]

执行预处理步骤,再次画图查看:

代码语言:javascript
复制
segdata_boxcox <- bake(preproc, new_data = NULL)

ggplot(segdata_boxcox, aes(x = AreaCh1))+
  geom_histogram(bins = 10)

plot of chunk unnamed-chunk-12

添加交互项

代码语言:javascript
复制
step_interact()

解决离群值

代码语言:javascript
复制
data(biomass, package = "modeldata")

biomass_tr <- biomass[biomass$dataset == "Training", ]
biomass_te <- biomass[biomass$dataset == "Testing", ]

# 建立菜谱
rec <- recipe(
  HHV ~ carbon + hydrogen + oxygen + nitrogen + sulfur,
  data = biomass_tr
)

# 添加食材
ss_trans <- rec %>%
  step_center(carbon, hydrogen) %>%
  step_scale(carbon, hydrogen) %>%
  step_spatialsign(carbon, hydrogen)

# 准备好了,可以下锅了
ss_obj <- prep(ss_trans, training = biomass_tr)

# 下锅制作
transformed_te <- bake(ss_obj, biomass_te)

# 画图查看之前的
plot(biomass_te$carbon, biomass_te$hydrogen)

plot of chunk unnamed-chunk-14

代码语言:javascript
复制
# 画图查看之后的
plot(transformed_te$carbon, transformed_te$hydrogen)

plot of chunk unnamed-chunk-14

代码语言:javascript
复制
# 获取数据预处理步骤
tidy(ss_trans, number = 3)
## # A tibble: 2 × 2
##   terms    id               
##   <chr>    <chr>            
## 1 carbon   spatialsign_BPYzj
## 2 hydrogen spatialsign_BPYzj
tidy(ss_obj, number = 3)
## # A tibble: 2 × 2
##   terms    id               
##   <chr>    <chr>            
## 1 carbon   spatialsign_BPYzj
## 2 hydrogen spatialsign_BPYzj

数据降维和特征提取

常用的方法如下,看名字就知道是哪些方法,如果你看到这些名字不认识,说明你可能还不适合看这个教程,先去学习下一些降维的基础知识。

代码语言:javascript
复制
step_pca()
step_ica()
step_nnmf()
step_pls()

缺失值

recipes中缺失值插补的方法非常多,所有都是以step_impute_xxx的形式出现,而且名字简单易懂,大家选择合适的即可!

代码语言:javascript
复制
step_impute_bag()
step_impute_knn()
step_impute_linear()
step_impute_lower()
step_impute_mean()
step_impute_median()
step_impute_mode()
step_impute_roll()

移除预测变量

移除预测变量其实属于特征选择内容,这部分内容在caret包的教程中有详细的介绍,大家可以搜索历史推文。

代码语言:javascript
复制
step_corr()
step_filter()
step_filter_missing()
step_lincomb()
step_zv()
step_nzv()
step_rm()
step_select()

创建虚拟变量

比如创建哑变量等,还包括对因子型变量的常见处理,和forcats包做的事情非常相似,大家可以参考我们的forcats包系列推文:

代码语言:javascript
复制
step_dummy()
step_bin2factor()
step_factor2string()
step_string2factor()
step_num2factor()
step_other()
step_percentile()
step_unknown()

区间化预测变量

主要是对变量进行分箱操作。

代码语言:javascript
复制
step_cut()
step_discretize()

以上就是recipes中常见的数据预处理步骤,它的用法很简单,语法非常统一,还是比较容易记住的,所以只演示了前几个,这里的每一个数据预处理步骤的具体细节以及产生的相应变化,我都在前几篇推文中详细解释过了,所以这里只是列出了一些函数名字,并没有进行具体的演示哦~

除此之外,还有一些数据预处理的函数我没有介绍,比如**样条变换(就是大家喜欢的立方样条、β样条等)**,感兴趣的可以自己了解下。

后面会继续为大家介绍mlr3中的数据预处理方法。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-06-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 医学和生信笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 加载R包
  • 中心化和标准化
  • 去除偏度
  • 添加交互项
  • 解决离群值
  • 数据降维和特征提取
  • 缺失值
  • 移除预测变量
  • 创建虚拟变量
  • 区间化预测变量
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档