r - 如何根据r中的多个变量拆分数据?
问题描述
我想将我的数据分成几乎均匀大小的训练和测试集,以实现两个样本中变量“年龄”、“性别”和“扫描仪”的几乎相等(尽可能相等)的分布。变量“站点”的组应分开(例如训练集中的 S01、S03、S04、S10、.. 和测试集中的 S02、S05、S06、...)。我的示例数据如下所示:
set.seed(2)
data <- data.frame(sex = sample(c("f","m"), 6500, replace=TRUE, prob = c(0.52, 0.48)),
scanner = sample(c("x", "Y"), 6500, replace = TRUE, prob = c(0.25, 0.75)),
site = sample(c("S01", "S02", "S03", "S04", "S05", "S06", "S07", "S08", "S09", "S10", "S11", "S12", "S13", "S14",
"S15", "S16", "S17","S18", "S19"), 6500, replace = TRUE, prob = c(.04, .07, .05, .04, .07, .04, .03,
.05, .07, .04, .07, .07, .04, .12,
.04, .08, .04, .02, .02)),
age = rnorm(6500, mean = 117.5, sd = 8.5))
有谁知道如何做到这一点?很感谢任何形式的帮助!
解决方案
minDiff包中的create_groups
函数可能是您正在寻找的。
描述
用于将一组项目分配给 N 个组。就特定标准而言,组之间的差异被最小化(例如:最小化学校班级之间平均考试成绩的差异)。
对于这个问题,site
变量是固定的——值必须在训练数据集和测试数据集之间分开。因此,聚合其他标准site
,然后在函数中使用此聚合数据集,其中用于最小化差异的标准是平均年龄和 sd 年龄,以及男性(或女性)和扫描仪类型“Y”(或“ X”)。
install.packages("remotes")
remotes::install_github("m-Py/minDiff")
library(minDiff)
library(dplyr)
Sites <- data %>%
group_by(site) %>%
summarise(n=n(),
sex_m=sum(sex=="m")/n(),
scanner_Y=sum(scanner=="Y")/n(),
age_mu=mean(age),
age_sd=sd(age)) %>%
as.data.frame() # `create_groups` only accepts pure data frames, tbls aren't allowed.
现在基于此聚合数据框创建 2 个组。
Sites <- create_groups(Sites,
criteria_scale=names(Sites)[-1],
sets_n=2,
equalize=list(mean, sd),
exact=TRUE, # gives "optimum" result.
# FALSE is quicker but tries only 100 samples at random
talk=TRUE) # show the progress as it takes a while...
结果(大约 2 分钟后)是一个数据框,其中包含一个名为 的新变量newSet
。
head(Sites)
# site n sex_m scanner_Y age_mu age_sd newSet
#1 S01 244 0.4959016 0.7377049 118.3024 8.292912 2
#2 S02 466 0.5107296 0.7575107 117.1656 8.491649 2
#3 S03 354 0.4548023 0.7175141 117.6626 8.095703 1
#4 S04 263 0.5247148 0.7870722 118.2087 8.475679 1
#5 S05 438 0.5319635 0.7488584 117.6617 8.826479 1
#6 S06 249 0.5180723 0.7510040 117.0743 8.090794 2
我们可以检查两组之间的变量分布:
aggregate(cbind(n,sex_m, scanner_Y, age_mu, age_sd)~newSet, FUN=sum, data=Sites)
# newSet n sex_m scanner_Y age_mu age_sd
#1 1 3450 4.826725 7.599581 1174.639 84.71687
#2 2 3050 4.267651 6.828945 1057.254 76.60529
还不错。现在将此数据与原始数据合并。
dataSet <- merge(data, subset(Sites, select=c("site","newSet")))
我们现在可以检查整个数据中变量的分布。
dataSet %>%
group_by(newSet) %>%
summarise(n=n(),
sex_m=sum(sex=="m")/n(),
scanner_Y=sum(scanner=="Y")/n(),
age_mu=mean(age),
age_sd=sd(age))
# A tibble: 2 x 6
newSet n sex_m scanner_Y age_mu age_sd
<int> <int> <dbl> <dbl> <dbl> <dbl>
1 1 3450 0.486 0.757 118. 8.42
2 2 3050 0.482 0.759 118. 8.49
似乎有道理。样本量差别不大,但男性和“Y”型扫描仪类型的比例非常接近,年龄分布也是如此。
然后,您可以创建训练和测试数据集。
train <- filter(dataSet, newSet==1)
test <- filter(dataSet, newSet==2)
推荐阅读
- r - 使用 R 中的 gt 包更改存根行组中的缩进
- rest - Google Drive API Resumable Upload PUT 请求失败。状态码:400。消息:未找到
- css - 纵向查看时,英雄图像不是全高
- android - 设置中的字体大小使 TextView 中的文本不可读且重叠
- docker - Gcloud 和 docker 混淆
- spring-boot - 在集群模式下运行 Hibernate
- flutter - 在 Dart 中使用三重移位 (>>>) 运算符
- kubernetes - Airflow - 从 Kubernetes 中运行的气流访问 REST API
- javascript - 选择选项是选择上一个选择选项不会隐藏/不显示的选项
- android - 使用改造,D/json 制作新闻应用程序:java.lang.IllegalStateException:预期 BEGIN_OBJECT 但在第 1 行第 2 列路径 $ 处为 BEGIN_ARRAY