在R中随机抽样数据帧为3组

时间:2015-12-01 19:19:41

标签: r random-sample

目标:将数据帧随机分成3个样本。

  • 一个包含60%行的样本
  • 其他两个样本,行数为20%
  • 样品不应与其他样品重复(即样品无需更换)。

这是一个笨重的解决方案:

allrows <- 1:nrow(mtcars)

set.seed(7)
trainrows <- sample(allrows, replace = F, size = 0.6*length(allrows))
test_cvrows <- allrows[-trainrows]
testrows <- sample(test_cvrows, replace=F, size = 0.5*length(test_cvrows))
cvrows <- test_cvrows[-which(test_cvrows %in% testrows)]

train <- mtcars[trainrows,]
test <- mtcars[testrows,]
cvr <- mtcars[cvrows,]

必须有一些更容易的东西,也许在一个包中。 dplyr具有sample_frac功能,但这似乎针对单个样本,而不是分成多个样本。

关闭,但不是这个问题的答案: Random Sample with multiple probabilities in R

4 个答案:

答案 0 :(得分:8)

你需要分区准确吗?如果没有,

set.seed(7)
ss <- sample(1:3,size=nrow(mtcars),replace=TRUE,prob=c(0.6,0.2,0.2))
train <- mtcars[ss==1,]
test <- mtcars[ss==2,]
cvr <- mtcars[ss==3,]

应该这样做。

或者,正如@Frank在评论中所说,您可以split()原始数据将它们作为列表的元素:

mycars <- setNames(split(mtcars,ss), c("train","test","cvr"))

答案 1 :(得分:1)

不是最漂亮的解决方案(特别是对于较大的样本),但它确实有效。

file_uploads = On
upload_tmp_dir = /var/www/tmpdir/
upload_max_filesize = 1024M

答案 2 :(得分:0)

无需替换的选项

使用插入包。

library(caret)

inTrain <- createDataPartition(mtcars$mpg, p = 0.6, list = FALSE)
train <- mtcars[inTrain, ]
inTest <- createDataPartition(mtcars$mpg[-inTrain], list = FALSE)
test <- mtcars[-inTrain,][inTest, ]
cvr <- mtcars[-inTrain,][-inTest, ]

基础包。

## splitData
# y column of data to create split on
# p list of percentage split
splitData <- function(y, p = c(0.5)){
  if(sum(p) > 1){
    stop("sum of p cannot exceed 1")
  }

  rows <- 1:length(y)

  res <- list()

  n_sample = round(length(rows) * p)
  for( size in n_sample){
    inSplit <-  sample.int(length(rows), size)
    res <- c(res, list(rows[inSplit]))
    rows <- rows[-inSplit]
  }

  if(sum(as.matrix(p)) < 1){
    res <- c(res, list(rows))
  }

  res
}

split_example_2 <- splitData(mtcars$mpg, p = c(0.6, 0.2))
split_example_3 <- splitData(mtcars$mpg)

答案 3 :(得分:0)

如果您想获得每个组的准确且可复制的数字(请记住,组的大小必须是整数,并尽可能接近比例地分割),而不是每次允许组大小随机变化您执行随机分割时,请尝试:

sample_size <- nrow(mtcars)
set_proportions <- c(Training = 0.6, Validation = 0.2, Test = 0.2)
set_frequencies <- diff(floor(sample_size * cumsum(c(0, set_proportions))))
mtcars$set <- sample(rep(names(set_proportions), times = set_frequencies))

然后,您可以简单地通过以下方式将其拆分为数据帧列表

mtcars <- split(mtcars, mtcars$set)

例如验证集的数据框现在以mtcars$Validation的形式访问,或者您也可以拆分为以下单独的数据框:

mtcars_train <- mtcars[mtcars$set == "Training", ]
mtcars_validation <- mtcars[mtcars$set == "Validation", ]
mtcars_test <- mtcars[mtcars$set == "Test", ]

在某些情况下,例如这种情况,您无法精确地拆分数据60%,20%,20%,但是这种方法保证了两个20%集的大小彼此之间不应超过一个:

> set_frequencies
  Training Validation       Test 
        19          6          7

检查它是否按预期工作:

> table(mtcars$set)

      Test   Training Validation 
         7         19          6 

(基于Ben Bolker的回答和liori的评论。)