Cách chia dữ liệu thành tập huấn luyện / kiểm tra bằng chức năng mẫu


160

Tôi mới bắt đầu sử dụng R và tôi không chắc chắn cách kết hợp tập dữ liệu của mình với mã mẫu sau:

sample(x, size, replace = FALSE, prob = NULL)

Tôi có một bộ dữ liệu mà tôi cần đưa vào đào tạo (75%) và thử nghiệm (25%). Tôi không chắc chắn những thông tin nào tôi nên đưa vào x và kích thước? Là x tập tin dữ liệu, và kích thước tôi có bao nhiêu mẫu?


1
xcó thể là chỉ số (hàng / col nos. say) của bạn data. sizecó thể 0.75*nrow(data). Hãy thử sample(1:10, 4, replace = FALSE, prob = NULL)xem những gì nó làm.
harkmug

Câu trả lời:


255

Có nhiều cách tiếp cận để đạt được phân vùng dữ liệu. Để có cách tiếp cận đầy đủ hơn, hãy xem createDataPartitionchức năng trong caToolsgói.

Đây là một ví dụ đơn giản:

data(mtcars)

## 75% of the sample size
smp_size <- floor(0.75 * nrow(mtcars))

## set the seed to make your partition reproducible
set.seed(123)
train_ind <- sample(seq_len(nrow(mtcars)), size = smp_size)

train <- mtcars[train_ind, ]
test <- mtcars[-train_ind, ]

Tôi hơi bối rối điều gì đảm bảo mã này trả về một bài kiểm tra duy nhất và đào tạo df? Nó dường như làm việc, đừng hiểu sai ý tôi. Chỉ cần gặp khó khăn trong việc làm thế nào trừ đi các chỉ số dẫn đến quan sát độc đáo. Chẳng hạn, nếu bạn có một df có 10 hàng và một cột và một cột chứa 1,2,3,4,5,6,7,8,9,10 và bạn đã tuân theo mã này, điều gì ngăn cản một đoàn tàu có chỉ số 4 và kiểm tra có -6 -> 10 - 6 = 4 là tốt?
goldisfine

1
cảm tạ. Tôi đã thử mtcars[!train_ind]và trong khi nó không thất bại, nó đã không hoạt động như mong đợi. Làm thế nào tôi có thể tập hợp con bằng cách sử dụng !?
user989762

@ user989762 !được sử dụng cho logic ( TRUE/FALSE) chứ không phải chỉ số. Nếu bạn muốn tập hợp con bằng cách sử dụng !, hãy thử một cái gì đó như mtcars [ !seq_len(nrow(mtcars)) %in% train_ind,] (chưa được kiểm tra).
Dickoa

1
@VedaadShakib khi bạn sử dụng "-" nó bỏ qua tất cả các chỉ mục trong train_ind khỏi dữ liệu của bạn. Hãy xem adv-r.had.co.nz/Subetting.html . Hy vọng nó sẽ giúp
Dickoa

1
Không có createDataPartitiontrong caretvà khôngcaTools ?
J. Mini

93

Nó có thể được thực hiện dễ dàng bằng cách:

set.seed(101) # Set Seed so that same sample can be reproduced in future also
# Now Selecting 75% of data as sample from total 'n' rows of the data  
sample <- sample.int(n = nrow(data), size = floor(.75*nrow(data)), replace = F)
train <- data[sample, ]
test  <- data[-sample, ]

Bằng cách sử dụng gói caTools :

require(caTools)
set.seed(101) 
sample = sample.split(data$anycolumn, SplitRatio = .75)
train = subset(data, sample == TRUE)
test  = subset(data, sample == FALSE)

4
Gần đây tôi đã làm một khóa học với MIT và họ đã sử dụng phương pháp này bằng cách sử dụng caTools xuyên suốt. Cảm ơn
Chetan Sharma

1
sample = sample.split(data[,1], SplitRatio = .75)Nên loại bỏ sự cần thiết phải đặt tên cho một cột.
Benjamin Ziepert

33

Tôi sẽ sử dụng dplyrcho việc này, làm cho nó siêu đơn giản. Nó không yêu cầu một biến id trong tập dữ liệu của bạn, dù sao đó cũng là một ý tưởng tốt, không chỉ để tạo các bộ mà còn để truy xuất nguồn gốc trong dự án của bạn. Thêm nó nếu không có sẵn.

mtcars$id <- 1:nrow(mtcars)
train <- mtcars %>% dplyr::sample_frac(.75)
test  <- dplyr::anti_join(mtcars, train, by = 'id')

28

Đây gần như là cùng một mã, nhưng nhìn đẹp hơn

bound <- floor((nrow(df)/4)*3)         #define % of training and test set

df <- df[sample(nrow(df)), ]           #sample rows 
df.train <- df[1:bound, ]              #get training set
df.test <- df[(bound+1):nrow(df), ]    #get test set

Vâng Nhìn đẹp đấy!
MeenakshiSundharam

23
library(caret)
intrain<-createDataPartition(y=sub_train$classe,p=0.7,list=FALSE)
training<-m_train[intrain,]
testing<-m_train[-intrain,]

3
Trong khi một câu trả lời chỉ có mã là một câu trả lời, tốt hơn là cung cấp một số lời giải thích.
C8H10N4O2

m_train là gì? Tôi nghĩ bạn có nghĩa là, sub_train dữ liệu gốc.frame. Do đó, mã sửa đổi phải được đào tạo <-sub_train [intrain,] và thử nghiệm <-sub_train [-intrain,]. Tôi tự hỏi tại sao không ai có thể phát hiện ra vấn đề lớn này với câu trả lời của bạn trong năm năm qua!
mnm

21

Tôi sẽ chia 'a' thành tàu (70%) và kiểm tra (30%)

    a # original data frame
    library(dplyr)
    train<-sample_frac(a, 0.7)
    sid<-as.numeric(rownames(train)) # because rownames() returns character
    test<-a[-sid,]

làm xong


4
bạn cần nhập gói dpyr, yêu cầu (dplyr)
TheMI

Câu trả lời này đã giúp tôi nhưng tôi cần phải điều chỉnh nó để có kết quả như mong đợi. Như vậy, tập dữ liệu 'train' có rownames = sid của các số nguyên tuần tự: 1,2,3,4, ... trong khi bạn muốn sid trở thành chủ sở hữu từ tập dữ liệu gốc 'a,' vì chúng được chọn ngẫu nhiên đã thắng 't là các số nguyên tuần tự. Vì vậy, trước tiên cần tạo biến id trên 'a'.
Scott Murff

hàng.names (mtcars) <- NULL; đào tạo <-dplyr :: sample_frac (mtcars, 0,5); test <-mtcars [-as.numeric (row.names (train)),] # Tôi đã làm điều này với dữ liệu của mình, mã gốc không hoạt động nếu tên hàng của bạn đã được đặt thành số
Christopher John

16

Giải pháp của tôi về cơ bản giống như của Dickoa nhưng dễ giải thích hơn một chút:

data(mtcars)
n = nrow(mtcars)
trainIndex = sample(1:n, size = round(0.7*n), replace=FALSE)
train = mtcars[trainIndex ,]
test = mtcars[-trainIndex ,]

Biến số là gì?
billmccord

7

Chỉ là một cách ngắn gọn và đơn giản hơn bằng cách sử dụng thư viện dplyr tuyệt vời :

library(dplyr)
set.seed(275) #to get repeatable data

data.train <- sample_frac(Default, 0.7)

train_index <- as.numeric(rownames(data.train))
data.test <- Default[-train_index, ]

1
Bạn có nghĩa là để sử dụng Default[-train_index,]cho dòng cuối cùng.
Matt L.

5

Nếu bạn gõ:

?sample

Nếu sẽ khởi chạy một menu trợ giúp để giải thích ý nghĩa của các tham số của hàm mẫu.

Tôi không phải là một chuyên gia, nhưng đây là một số mã tôi có:

data <- data.frame(matrix(rnorm(400), nrow=100))
splitdata <- split(data[1:nrow(data),],sample(rep(1:4,as.integer(nrow(data)/4))))
test <- splitdata[[1]]
train <- rbind(splitdata[[1]],splitdata[[2]],splitdata[[3]])

Điều này sẽ cung cấp cho bạn 75% đào tạo và 25% kiểm tra.


5

Sau khi xem qua tất cả các phương pháp khác nhau được đăng ở đây, tôi không thấy ai sử dụng TRUE/FALSEđể chọn và bỏ chọn dữ liệu. Vì vậy, tôi nghĩ rằng tôi sẽ chia sẻ một phương pháp sử dụng kỹ thuật đó.

n = nrow(dataset)
split = sample(c(TRUE, FALSE), n, replace=TRUE, prob=c(0.75, 0.25))

training = dataset[split, ]
testing = dataset[!split, ]

Giải trình

Có nhiều cách chọn dữ liệu từ R, thông thường mọi người sử dụng các chỉ số dương / âm để chọn / bỏ chọn tương ứng. Tuy nhiên, các chức năng tương tự có thể đạt được bằng cách sử dụngTRUE/FALSE để chọn / bỏ chọn.

Hãy xem xét ví dụ sau.

# let's explore ways to select every other element
data = c(1, 2, 3, 4, 5)


# using positive indices to select wanted elements
data[c(1, 3, 5)]
[1] 1 3 5

# using negative indices to remove unwanted elements
data[c(-2, -4)]
[1] 1 3 5

# using booleans to select wanted elements
data[c(TRUE, FALSE, TRUE, FALSE, TRUE)]
[1] 1 3 5

# R recycles the TRUE/FALSE vector if it is not the correct dimension
data[c(TRUE, FALSE)]
[1] 1 3 5

4

Giải pháp của tôi xáo trộn các hàng, sau đó lấy 75% hàng đầu tiên làm tàu ​​và 25% cuối cùng làm thử nghiệm. Siêu mô phỏng!

row_count <- nrow(orders_pivotted)
shuffled_rows <- sample(row_count)
train <- orders_pivotted[head(shuffled_rows,floor(row_count*0.75)),]
test <- orders_pivotted[tail(shuffled_rows,floor(row_count*0.25)),]

4

Tôi có thể đề nghị sử dụng gói rsample:

# choosing 75% of the data to be the training data
data_split <- initial_split(data, prop = .75)
# extracting training data and test data as two seperate dataframes
data_train <- training(data_split)
data_test  <- testing(data_split)

3

scorecard gói có một chức năng hữu ích cho điều đó, nơi bạn có thể chỉ định tỷ lệ và hạt giống

library(scorecard)

dt_list <- split_df(mtcars, ratio = 0.75, seed = 66)

Dữ liệu kiểm tra và đào tạo được lưu trữ trong một danh sách và có thể được truy cập bằng cách gọi dt_list$traindt_list$test


2

Bên dưới một chức năng tạo ra một listmẫu phụ có cùng kích thước không chính xác như những gì bạn muốn nhưng có thể chứng minh hữu ích cho những người khác. Trong trường hợp của tôi để tạo nhiều cây phân loại trên các mẫu nhỏ hơn để kiểm tra quá mức:

df_split <- function (df, number){
  sizedf      <- length(df[,1])
  bound       <- sizedf/number
  list        <- list() 
  for (i in 1:number){
    list[i] <- list(df[((i*bound+1)-bound):(i*bound),])
  }
  return(list)
}

Thí dụ :

x <- matrix(c(1:10), ncol=1)
x
# [,1]
# [1,]    1
# [2,]    2
# [3,]    3
# [4,]    4
# [5,]    5
# [6,]    6
# [7,]    7
# [8,]    8
# [9,]    9
#[10,]   10

x.split <- df_split(x,5)
x.split
# [[1]]
# [1] 1 2

# [[2]]
# [1] 3 4

# [[3]]
# [1] 5 6

# [[4]]
# [1] 7 8

# [[5]]
# [1] 9 10

2

Sử dụng gói caTools trong mã mẫu R sẽ như sau: -

data
split = sample.split(data$DependentcoloumnName, SplitRatio = 0.6)
training_set = subset(data, split == TRUE)
test_set = subset(data, split == FALSE)

2

Sử dụng cơ sở R. Hàm runiftạo các giá trị phân phối đồng đều từ 0 đến 1.By giá trị ngưỡng khác nhau (ví dụ train.size trong ví dụ bên dưới), bạn sẽ luôn có cùng tỷ lệ phần trăm của các bản ghi ngẫu nhiên bên dưới giá trị ngưỡng.

data(mtcars)
set.seed(123)

#desired proportion of records in training set
train.size<-.7
#true/false vector of values above/below the cutoff above
train.ind<-runif(nrow(mtcars))<train.size

#train
train.df<-mtcars[train.ind,]


#test
test.df<-mtcars[!train.ind,]

Đây sẽ là một câu trả lời tốt hơn nhiều nếu nó cho thấy các dòng bổ sung để thực sự tạo ra các bộ huấn luyện và kiểm tra (mà những người mới thường phải vật lộn với).
Gregor Thomas

2

Giả sử df là khung dữ liệu của bạn và bạn muốn tạo 75% đào tạo25% kiểm tra

all <- 1:nrow(df)
train_i <- sort(sample(all, round(nrow(df)*0.75,digits = 0),replace=FALSE))
test_i <- all[-train_i]

Sau đó, để tạo một khung dữ liệu xe lửa và thử nghiệm

df_train <- df[train_i,]
df_test <- df[test_i,]

1
require(caTools)

set.seed(101)            #This is used to create same samples everytime

split1=sample.split(data$anycol,SplitRatio=2/3)

train=subset(data,split1==TRUE)

test=subset(data,split1==FALSE)

Các sample.split()chức năng sẽ bổ sung thêm một cột 'split1' để dataframe và 2/3 hàng sẽ có giá trị này là TRUE và những người khác như FALSE.Now các hàng nơi split1 là TRUE sẽ được sao chép vào xe lửa và các hàng khác sẽ được sao chép vào thử nghiệm khung dữ liệu.


1

Tôi va vào cái này, nó cũng có thể giúp được.

set.seed(12)
data = Sonar[sample(nrow(Sonar)),]#reshufles the data
bound = floor(0.7 * nrow(data))
df_train = data[1:bound,]
df_test = data[(bound+1):nrow(data),]

1

Chúng ta có thể chia dữ liệu thành một tỷ lệ cụ thể ở đây là 80% đào tạo và 20% trong một tập dữ liệu thử nghiệm.

ind <- sample(2, nrow(dataName), replace = T, prob = c(0.8,0.2))
train <- dataName[ind==1, ]
test <- dataName[ind==2, ]

0

Cảnh giác samplevới việc chia tách nếu bạn tìm kiếm kết quả có thể lặp lại. Nếu dữ liệu của bạn thay đổi thậm chí một chút, sự phân chia sẽ thay đổi ngay cả khi bạn sử dụngset.seed . Ví dụ: hãy tưởng tượng danh sách ID được sắp xếp trong dữ liệu của bạn là tất cả các số trong khoảng từ 1 đến 10. Nếu bạn chỉ bỏ một quan sát, giả sử 4, lấy mẫu theo vị trí sẽ mang lại kết quả khác nhau vì hiện tại 5 đến 10 địa điểm đã di chuyển.

Một phương pháp khác là sử dụng hàm băm để ánh xạ ID thành một số số ngẫu nhiên giả và sau đó lấy mẫu trên mod của những số này. Mẫu này ổn định hơn vì sự phân công hiện được xác định bởi hàm băm của mỗi quan sát chứ không phải bởi vị trí tương đối của nó.

Ví dụ:

require(openssl)  # for md5
require(data.table)  # for the demo data

set.seed(1)  # this won't help `sample`

population <- as.character(1e5:(1e6-1))  # some made up ID names

N <- 1e4  # sample size

sample1 <- data.table(id = sort(sample(population, N)))  # randomly sample N ids
sample2 <- sample1[-sample(N, 1)]  # randomly drop one observation from sample1

# samples are all but identical
sample1
sample2
nrow(merge(sample1, sample2))

[1] 9999

# row splitting yields very different test sets, even though we've set the seed
test <- sample(N-1, N/2, replace = F)

test1 <- sample1[test, .(id)]
test2 <- sample2[test, .(id)]
nrow(test1)

[1] 5000

nrow(merge(test1, test2))

[1] 2653

# to fix that, we can use some hash function to sample on the last digit

md5_bit_mod <- function(x, m = 2L) {
  # Inputs: 
  #  x: a character vector of ids
  #  m: the modulo divisor (modify for split proportions other than 50:50)
  # Output: remainders from dividing the first digit of the md5 hash of x by m
  as.integer(as.hexmode(substr(openssl::md5(x), 1, 1)) %% m)
}

# hash splitting preserves the similarity, because the assignment of test/train 
# is determined by the hash of each obs., and not by its relative location in the data
# which may change 
test1a <- sample1[md5_bit_mod(id) == 0L, .(id)]
test2a <- sample2[md5_bit_mod(id) == 0L, .(id)]
nrow(merge(test1a, test2a))

[1] 5057

nrow(test1a)

[1] 5057

cỡ mẫu không chính xác 5000 vì sự phân công là xác suất, nhưng nó không phải là vấn đề trong các mẫu lớn nhờ vào luật số lượng lớn.

Xem thêm: http://blog.richardweiss.org/2016/12/25/hash-splits.html/crypto/20742/statistic-properies-of-hash-fifts-when tính toán-modulo


Đã thêm dưới dạng một câu hỏi riêng biệt: stackoverflow.com/questions/52769681/ từ
dzeltzer

Tôi muốn phát triển mô hình auto.arima từ dữ liệu chuỗi nhiều thời gian và tôi muốn sử dụng 1 năm dữ liệu, 3 năm dữ liệu, 5, 7 ... trong khoảng thời gian hai năm từ mỗi chuỗi để xây dựng mô hình và thử nghiệm nó trong bộ thử nghiệm còn lại. Làm thế nào để tôi thực hiện việc đặt lại để mô hình được trang bị sẽ có những gì tôi muốn? Tôi đánh giá cao sự giúp đỡ của bạn
Stackuser

0
set.seed(123)
llwork<-sample(1:length(mydata),round(0.75*length(mydata),digits=0)) 
wmydata<-mydata[llwork, ]
tmydata<-mydata[-llwork, ]

-2

Có một cách rất đơn giản để chọn một số hàng bằng chỉ số R cho các hàng và cột. Điều này cho phép bạn phân chia rõ ràng bộ dữ liệu được cung cấp cho một số hàng - giả sử là 80% dữ liệu đầu tiên của bạn.

Trong R, tất cả các hàng và cột được lập chỉ mục, vì vậy DataSetName [1,1] là giá trị được gán cho cột đầu tiên và hàng đầu tiên của "DatasetName". Tôi có thể chọn các hàng bằng [x,] và các cột bằng [, x]

Ví dụ: Nếu tôi có một tập dữ liệu được đặt tên thuận tiện là "dữ liệu" với 100 hàng, tôi có thể xem 80 hàng đầu tiên bằng cách sử dụng

Xem (dữ liệu [1:80,])

Theo cùng một cách tôi có thể chọn các hàng này và tập hợp chúng bằng cách sử dụng:

tàu = dữ liệu [1:80,]

kiểm tra = dữ liệu [81: 100,]

Bây giờ tôi có dữ liệu của tôi được chia thành hai phần mà không có khả năng lấy mẫu lại. Nhanh chóng và dễ dàng.


1
Mặc dù đúng là dữ liệu có thể được phân chia theo cách đó, nó không được khuyến khích. Một số bộ dữ liệu được sắp xếp theo một biến mà bạn không biết. Vì vậy, tốt nhất để lấy mẫu hàng nào sẽ được coi là đào tạo thay vì lấy n hàng đầu tiên.
user5029763

1
Nếu bạn xáo trộn dữ liệu trước khi tách chúng để kiểm tra và tập huấn luyện, đề xuất của bạn sẽ hoạt động.
Hadij
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.