[英]Randomly sample data frame into 3 groups in R
目標:將數據幀隨機分成3個樣本。
這是一個笨重的解決方案:
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
函數,但似乎是針對單個樣本,而不是分割為多個樣本。
關閉,但不是這個問題的答案: R中有多個概率的隨機樣本
你需要分區准確嗎? 如果不,
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"))
不是最漂亮的解決方案(特別是對於較大的樣品),但它的工作原理。
n = nrow(mtcars)
#use different rounding for differet sizes/proportions
times =rep(1:3,c(0.6*n,0.2*n,0.2*n))
ntimes = length(times)
if (ntimes < n)
times = c(times,sample(1:3,n-ntimes,prob=c(0.6,0.2,0.2),replace=FALSE))
sets = sample(times)
df1 = mtcars[sets==1,]
df2 = mtcars[sets==2,]
df3 = mtcars[sets==3,]
選項無需替換
使用插入包。
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)
如果您希望為每個組獲得准確且可重現的數字(按照您可以實現的比例分組,請記住組大小必須是整數),而不是每次執行您的組時允許組大小隨機變化隨機拆分,試試:
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的評論。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.