簡體   English   中英

在R中隨機抽樣數據幀為3組

[英]Randomly sample data frame into 3 groups in R

目標:將數據幀隨機分成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函數,但似乎是針對單個樣本,而不是分割為多個樣本。

關閉,但不是這個問題的答案: 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM