R中的分层数据分割

Pro*_*oob 5 r machine-learning caret splitstackshape

我一直在使用caret::createDataPartition()以分层方式分割数据。现在我正在尝试我在堆栈中找到的另一种方法,即 ,splitstackshape::stratified()我对此感兴趣的原因是它允许根据我手动选择的功能进行分层,非常方便。

我在分割数据时遇到问题:

library(splitstackshape)

set.seed(40)
Train = stratified(Data, c('age','gender','treatment_1','treatment_2','cancers'), 0.75)
Run Code Online (Sandbox Code Playgroud)

这会产生训练集,但是如何获得测试集呢?我没明白。我createDataPartition一路累了:

INDEX = stratified(Data, c('age','gender','treatment_1','treatment_2','cancers'), 0.75)
Train = Data[INDEX , ]
Test = Data[-INDEX ,]
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为stratified创建的是实际的列车数据,而不是索引。

那么如何使用这个函数获取测试数据呢?谢谢!

Len*_*ski 2

如果向数据添加唯一的顺序行标识符,则可以使用它来提取未为训练数据帧选择的行,如下所示。我们将使用mtcars一个可重现的示例。

library(splitstackshape)
set.seed(19108379) # for reproducibility

# add a unique sequential ID to track rows in the sample, using mtcars

mtcars$rowId <- 1:nrow(mtcars)

# take a stratified sample by cyl

train <- stratified(mtcars,"cyl",size = 0.6)

test <- mtcars[!(mtcars$rowId %in% train$rowId),]

nrow(train) + nrow(test) # should add to 32 
Run Code Online (Sandbox Code Playgroud)

...以及输出:

> nrow(train) + nrow(test) # should add to 32 
[1] 32
Run Code Online (Sandbox Code Playgroud)

下一级别的详细信息...

stratified()函数根据传递给函数的 by groups 提取一组行。通过添加rowId字段,我们可以跟踪训练数据中包含的观察结果。

> # list the rows included in the sample
> train$rowId
 [1]  6 11 10  4  3 27 18  8  9 21 28 23 17 16 29 22 15  7 14
> nrow(train)
[1] 19
Run Code Online (Sandbox Code Playgroud)

然后,我们使用提取运算符通过 ! 创建测试数据帧。操作员:

> # illustrate the selection criteria used to extract rows not in the training data
> !(mtcars$rowId %in% train$rowId)
 [1]  TRUE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE
[15] FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE
[29] FALSE  TRUE  TRUE  TRUE
> 
Run Code Online (Sandbox Code Playgroud)

最后,根据选择标准,我们计算测试数据框中要包含的行数,该行数应等于 32 - 19 或 13:

> # count rows to be included in test data frame 
> sum(!(mtcars$rowId %in% train$rowId)) # should add to 13
[1] 13
Run Code Online (Sandbox Code Playgroud)

与 BothSets 参数的比较

另一个答案指出,该stratified()函数包含一个参数bothSets,它生成一个包含采样数据和剩余数据的列表。我们可以如下证明这两种方法的等效性。

# alternative answer: use the package's bothSets argument
set.seed(19108379)
sampleData <- stratified(mtcars,"cyl",size = 0.6,bothSets = TRUE)

# compare rowIds in test vs. SAMP2 data frames
sampleData$SAMP2$rowId
test$rowId
Run Code Online (Sandbox Code Playgroud)

...以及输出:

> sampleData$SAMP2$rowId
 [1]  1  2  5 12 13 19 20 24 25 26 30 31 32
> test$rowId
 [1]  1  2  5 12 13 19 20 24 25 26 30 31 32
> 
Run Code Online (Sandbox Code Playgroud)

最后评论

值得注意的是,caret::createDataPartition()通常用于根据因变量的值分割数据,因此trainingtest分区在因变量的值之间具有相对相等的表示。

相反,stratified()根据一个或多个特征(即自变量)的组合进行划分。基于自变量的分区有可能在训练和测试分区中的因变量值的分布中引入变异性。也就是说,训练分区中因变量值的分布可能与测试分区中因变量分布显着不同。