You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用caret包的createDataPartition生成不均衡训练测试集求助

问题描述

使用R语言的caret包将77行无缺失值的数据划分为训练集和测试集,设置参数p=0.8后,createDataPartition函数却生成了仅4行的训练集和73行的测试集,结果不符合预期。

用户代码如下:

library(caret)
# Split data into train and test
set.seed(123)
data.full <- data.full %>% select(fasting_status, a1c, glu, uc_ratio)
training.samples <- data.full %>% 
  createDataPartition(p = 0.8, list = FALSE)
Warning messages:
1: In createDataPartition(., p = 0.8, list = FALSE) :
  Some classes have no records (  ) and these will be ignored
2: In createDataPartition(., p = 0.8, list = FALSE) :
  Some classes have a single record (  ) and these will be selected for the sample
train.data  <- data.full[training.samples, ]
test.data <- data.full[-training.samples, ] 

可复现数据:

dput(data.full)
structure(list(fasting_status = structure(c(1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L), levels = c("1", "2"), class = "factor"), 
    a1c = c(4.3, 4.5, 4.4, 2.9, 4.3, 4.4, 4.2, 4.5, 4.2, 4.2, 
    4.5, 4.5, 4.8, 4.5, 5.2, 4.9, 4.6, 4.2, 4.4, 4.9, 4.6, 4.5, 
    4.4, 4.8, 4.5, 4.1, 3.8, 3.1, 4.3, 4.6, 4.7, 4.9, 4.6, 4.4, 
    3.1, 4.6, 4.4, 4.2, 4.4, 5.2, 4.4, 5.1, 4.6, 4.7, 5.2, 4.7, 
    4.7, 4.6, 4.4, 4.4, 4.2, 4.5, 4.6, 4.4, 3.2, 4.8, 5.2, 5.2, 
    4.6, 4.9, 5.6, 4.6, 4.9, 4.5, 5.1, 4.6, 4.9, 4.6, 4.3, 4.6, 
    4.6, 4.3, 4.6, 4.3, 4.6, 6.5, 4.8), glu = c(88.5, 98, 117.5, 
    53, 108.5, 106, 105, 101, 91, 99.5, 128.5, 113, 114, 121.5, 
    121, 131.5, 160.5, 96, 110, 140, 119.5, 115.3, 112, 143.5, 
    116.5, 116.5, 111, 139.5, 123.5, 131, 113, 137, 114, 98.5, 
    124.5, 123.5, 111.5, 111, 127, 123, 137.5, 119, 107, 130.5, 
    142.5, 115, 133.5, 119, 148.3, 125.5, 138.5, 106.5, 153.5, 
    126.5, 179, 145, 143, 124.5, 134, 146.5, 127.5, 124.5, 123, 
    129, 145.3, 125.5, 146.5, 153.5, 115.5, 128, 110.5, 131, 
    139.5, 124, 154, 94, 76.3), uc_ratio = c(30.65603924, 15.32801962, 
    60.59075991, 7.39973361, 57.84661317, 27.46781116, 16.0944206, 
    6.131207848, 94.61568474, 19.50838861, 7.803355443, 19.41549152, 
    7.464079119, 19.67095851, 29.50643777, 62.94706724, 80.472103, 
    25.75107296, 73.57449418, 39.01677721, 41.13018598, 10.62933697, 
    7.803355443, 30.04291845, 32.75355771, 49.52129416, 5.969860273, 
    22.72153497, 7.153075823, 75.61823012, 23.50296342, 53.64806867, 
    11.19611891, 38.25340549, 88.36152487, 51.50214592, 9.196811772, 
    41.98544505, 6.35828962, 9.196811772, 94.87237407, 12.87553648, 
    6.035407725, 7.39973361, 10.72961373, 11.70503316, 9.035464197, 
    16.34988759, 11.68917269, 35.11509949, 61.85306741, 11.36076748, 
    12.2624157, 7.153075823, 14.30615165, 10.40447392, 3.901677721, 
    52.11526671, 21.45922747, 30.49469166, 81.06819266, 1.950838861, 
    34.33476395, 8.0472103, 24.94635193, 9.754194304, 64.3776824, 
    9.196811772, 11.92179304, 34.87124464, 74.39198856, 124.4635193, 
    13.79521766, 5.722460658, 66.76204101, 69.9757432, 19.50838861
    )), row.names = c(NA, -77L), class = "data.frame")
问题原因与解决方法

原因分析

createDataPartition的核心逻辑是按指定变量分层抽样,默认会将传入的第一个参数当作分层依据(y参数)。你用管道符直接把整个数据框传给函数,导致它误将整个数据框作为分层变量,而非目标分类列fasting_status。这种情况下函数无法正确识别类别,进而出现抽样结果异常,同时触发警告提示类别记录异常。

查看数据中真实的类别分布:

table(data.full$fasting_status)
# 输出:
# 1  2 
#39 38

解决方法

方法1:明确指定分层变量(推荐)

直接通过y参数传入你的分类变量fasting_status,让函数基于该变量按比例分层抽样,保证训练集和测试集的类别分布一致:

library(caret)
library(dplyr)

set.seed(123)
data.full <- data.full %>% select(fasting_status, a1c, glu, uc_ratio)
# 明确指定y参数为分类变量
training.samples <- createDataPartition(y = data.full$fasting_status, p = 0.8, list = FALSE)

train.data  <- data.full[training.samples, ]
test.data <- data.full[-training.samples, ] 

# 验证结果
nrow(train.data)  # 62行(符合77*0.8的比例)
nrow(test.data)   # 15行
table(train.data$fasting_status)  # 类别比例与原数据一致:1类31行,2类31行

方法2:简单随机抽样(无需分层)

如果不需要保持类别比例,仅需简单随机划分,可直接使用sample函数:

set.seed(123)
training.samples <- sample(1:nrow(data.full), size = floor(0.8*nrow(data.full)))

train.data <- data.full[training.samples, ]
test.data <- data.full[-training.samples, ]

内容的提问来源于stack exchange,提问作者burphound

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:49:51