Bagaimana membagi data menjadi set pelatihan / pengujian menggunakan fungsi sampel

160

Saya baru saja mulai menggunakan R dan saya tidak yakin bagaimana cara menggabungkan dataset saya dengan kode contoh berikut:

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

Saya memiliki dataset yang harus saya masukkan ke dalam set pelatihan (75%) dan pengujian (25%). Saya tidak yakin informasi apa yang harus saya masukkan ke dalam x dan ukuran? Apakah x file dataset, dan ukuran berapa sampel yang saya miliki?

Susie Humby
sumber
1
xdapat menjadi indeks (baris / kolom no. katakan) dari Anda data. sizebisa 0.75*nrow(data). Coba sample(1:10, 4, replace = FALSE, prob = NULL)lihat apa fungsinya.
harkmug

Jawaban:

255

Ada banyak pendekatan untuk mencapai partisi data. Untuk pendekatan yang lebih lengkap lihat createDataPartitionfungsi dalam caToolspaket.

Ini adalah contoh sederhana:

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, ]
dickoa
sumber
Saya agak bingung apa yang menjamin kode ini mengembalikan tes yang unik dan melatihnya? Tampaknya berhasil, jangan salah paham. Hanya mengalami kesulitan memahami bagaimana mengurangi indeks mengarah ke pengamatan unik. Misalnya, jika Anda memiliki df dengan 10 baris dan satu kolom, dan satu kolom berisi 1,2,3,4,5,6,7,8,9,10 dan Anda mengikuti kode ini, apa yang mencegah kereta memiliki indeks 4 dan tes memiliki -6 -> 10 - 6 = 4 juga?
goldisfine
1
terima kasih. Saya mencoba mtcars[!train_ind]dan meskipun tidak gagal, itu tidak berhasil seperti yang diharapkan. Bagaimana saya bisa mengelompokkan menggunakan !?
user989762
@ user989762 !digunakan untuk logis ( TRUE/FALSE) dan bukan indeks. Jika Anda ingin subset menggunakan !, coba sesuatu seperti mtcars [ !seq_len(nrow(mtcars)) %in% train_ind,] (tidak diuji).
dickoa
1
@VedaadShakib ketika Anda menggunakan "-" itu menghilangkan semua indeks di train_ind dari data Anda. Lihatlah adv-r.had.co.nz/Subsetting.html . Semoga ini bisa membantu
dickoa
1
Tidak createDataPartitionmasuk caretdan tidak caTools?
J. Mini
93

Ini dapat dengan mudah dilakukan dengan:

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, ]

Dengan menggunakan paket caTools :

require(caTools)
set.seed(101) 
sample = sample.split(data$anycolumn, SplitRatio = .75)
train = subset(data, sample == TRUE)
test  = subset(data, sample == FALSE)
TheMI
sumber
4
Saya baru-baru melakukan kursus dengan MIT dan mereka menggunakan pendekatan menggunakan caTools di seluruh. Terima kasih
Chetan Sharma
1
sample = sample.split(data[,1], SplitRatio = .75)Harus menghapus kebutuhan untuk memberi nama kolom.
Benjamin Ziepert
33

Saya akan menggunakan dplyrini, membuatnya sangat sederhana. Itu memang membutuhkan variabel id di set data Anda, yang merupakan ide bagus, tidak hanya untuk membuat set tetapi juga untuk keterlacakan selama proyek Anda. Tambahkan jika belum mengandung.

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

Ini hampir kode yang sama, tetapi dalam tampilan yang lebih bagus

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
Katerina
sumber
Ya! Kelihatan bagus!
MeenakshiSundharam
23
library(caret)
intrain<-createDataPartition(y=sub_train$classe,p=0.7,list=FALSE)
training<-m_train[intrain,]
testing<-m_train[-intrain,]
pradnya chavan
sumber
3
Sementara jawaban hanya kode adalah jawaban, lebih baik memberikan beberapa penjelasan.
C8H10N4O2
apa itu m_train? Saya pikir Anda maksud, sub_train data.frame asli. Oleh karena itu, kode yang direvisi harus melatih <-sub_train [intrain,] dan menguji <-sub_train [-intrain,]. Saya heran mengapa tidak ada yang bisa menemukan masalah besar ini dengan jawaban Anda dalam lima tahun terakhir!
mnm
21

Saya akan membagi 'a' menjadi kereta (70%) dan tes (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,]

selesai

hyunwoo jeong
sumber
4
Anda perlu mengimpor paket dpyr, memerlukan (dplyr)
TheMI
Jawaban ini membantu saya, tetapi saya perlu mengubahnya untuk mendapatkan hasil yang diharapkan. Seperti halnya, dataset 'train' memiliki rownames = sid of integer berurutan: 1,2,3,4, ... sedangkan Anda ingin sid menjadi rownumbers dari dataset asli 'a,' yang karena mereka dipilih secara acak akan dimenangkan akan menjadi bilangan bulat berurutan. Jadi, penting untuk membuat variabel id pada 'a' terlebih dahulu.
Scott Murff
row.names (mtcars) <- NULL; train <-dplyr :: sample_frac (mtcars, 0.5); test <-mtcars [-as.numeric (row.names (train)),] # Saya melakukan ini pada data saya, kode asli tidak berfungsi jika nama baris Anda sudah diatur ke angka
Christopher John
16

Solusi saya pada dasarnya sama dengan dickoa tetapi sedikit lebih mudah untuk ditafsirkan:

data(mtcars)
n = nrow(mtcars)
trainIndex = sample(1:n, size = round(0.7*n), replace=FALSE)
train = mtcars[trainIndex ,]
test = mtcars[-trainIndex ,]
AlexG
sumber
Apa itu variabel swiss?
billmccord
7

Hanya cara yang lebih singkat dan sederhana menggunakan perpustakaan dplyr yang mengagumkan :

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, ]
Shayan Amani
sumber
1
Apakah Anda bermaksud menggunakan Default[-train_index,]untuk baris terakhir.
Matt L.
5

Jika Anda mengetik:

?sample

Jika akan meluncurkan menu bantuan untuk menjelaskan apa arti parameter dari fungsi sampel.

Saya bukan ahli, tetapi ini beberapa kode yang saya miliki:

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]])

Ini akan memberi Anda 75% kereta dan 25% tes.

pengguna2502836
sumber
5

Setelah melihat semua metode berbeda yang diposting di sini, saya tidak melihat ada orang yang memanfaatkan TRUE/FALSEuntuk memilih dan membatalkan pilihan data. Jadi saya pikir saya akan berbagi metode menggunakan teknik itu.

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

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

Penjelasan

Ada beberapa cara untuk memilih data dari R, kebanyakan orang menggunakan indeks positif / negatif untuk memilih / tidak memilih masing-masing. Namun, fungsi yang sama dapat dicapai dengan menggunakanTRUE/FALSE untuk memilih / membatalkan pilihan.

Perhatikan contoh berikut.

# 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
Joe
sumber
4

Solusi saya mengocok baris, kemudian mengambil 75% pertama dari baris sebagai kereta dan 25% terakhir sebagai tes. Sangat simpel!

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)),]
Johnny V
sumber
4

Saya dapat menyarankan menggunakan paket 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)

sumber
3

scorecard Paket memiliki fungsi yang berguna untuk itu, di mana Anda dapat menentukan rasio dan seed

library(scorecard)

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

Data uji dan kereta disimpan dalam daftar dan dapat diakses dengan menelepon dt_list$traindandt_list$test

camnesia
sumber
2

Di bawah fungsi yang membuat listsub-sampel dengan ukuran yang sama yang tidak persis apa yang Anda inginkan tetapi mungkin terbukti bermanfaat bagi orang lain. Dalam kasus saya untuk membuat beberapa pohon klasifikasi pada sampel yang lebih kecil untuk menguji overfitting:

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)
}

Contoh:

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
Yohan Obadia
sumber
2

Gunakan paket caTools dalam kode sampel R adalah sebagai berikut: -

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

Gunakan basis R. Fungsi runifmenghasilkan nilai yang terdistribusi secara seragam dari 0 hingga 1. Dengan nilai cutoff yang bervariasi (train.size dalam contoh di bawah), Anda akan selalu memiliki kira-kira persentase yang sama dari catatan acak di bawah nilai cutoff.

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,]
Konstantin Mingoulin
sumber
Ini akan menjadi jawaban yang jauh lebih baik jika itu menunjukkan garis pasangan tambahan untuk benar-benar membuat set pelatihan dan tes (yang pemula sering kesulitan dengan).
Gregor Thomas
2

Dengan asumsi df adalah kerangka data Anda, dan Anda ingin membuat 75% train dan 25% test

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

Kemudian untuk membuat frame data kereta dan tes

df_train <- df[train_i,]
df_test <- df[test_i,]
Corentin
sumber
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)

The sample.split()fungsi akan menambah satu kolom tambahan 'split1' untuk dataframe dan 2/3 dari baris akan memiliki nilai ini sebagai BENAR dan lain-lain sebagai FALSE.Now baris mana split1 adalah TRUE akan disalin ke kereta dan baris lainnya akan disalin ke tes bingkai data.

Abhishek
sumber
1

Saya menabrak yang satu ini, itu bisa membantu juga.

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),]
pengguna322203
sumber
1

Kami dapat membagi data ke dalam rasio tertentu di sini adalah 80% kereta dan 20% dalam dataset uji.

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

Waspadalah sampleterhadap pemisahan jika Anda mencari hasil yang dapat direproduksi. Jika data Anda sedikit berubah, perpecahan akan bervariasi bahkan jika Anda menggunakannya set.seed. Misalnya, bayangkan daftar ID yang diurutkan dalam data Anda adalah semua angka antara 1 dan 10. Jika Anda hanya membatalkan satu pengamatan, katakanlah 4, pengambilan sampel berdasarkan lokasi akan menghasilkan hasil yang berbeda karena sekarang 5 hingga 10 semua tempat yang dipindahkan.

Metode alternatif adalah dengan menggunakan fungsi hash untuk memetakan ID menjadi beberapa angka acak semu dan kemudian sampel pada mod angka-angka ini. Sampel ini lebih stabil karena tugas sekarang ditentukan oleh hash dari setiap pengamatan, dan bukan oleh posisi relatifnya.

Sebagai contoh:

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

ukuran sampel tidak tepat 5000 karena penugasan adalah probabilistik, tetapi seharusnya tidak menjadi masalah dalam sampel besar berkat hukum angka besar.

Lihat juga: http://blog.richardweiss.org/2016/12/25/hash-splits.html dan /crypto/20742/statribution-properties-of-hash-functions-when -menghitung-modulo

dzeltzer
sumber
Ditambahkan sebagai pertanyaan terpisah: stackoverflow.com/questions/52769681/…
dzeltzer
Saya ingin mengembangkan model auto.arima dari beberapa data seri waktu dan saya ingin menggunakan data 1 tahun, data 3 tahun, 5, 7 ... dalam interval dua tahun dari setiap seri untuk membangun model dan mengujinya dalam set pengujian yang tersisa. Bagaimana saya melakukan subsetting sehingga model yang pas akan memiliki apa yang saya inginkan? Saya menghargai bantuan Anda
Stackuser
0
set.seed(123)
llwork<-sample(1:length(mydata),round(0.75*length(mydata),digits=0)) 
wmydata<-mydata[llwork, ]
tmydata<-mydata[-llwork, ]
Xavier Jiménez Albán
sumber
-2

Ada cara yang sangat sederhana untuk memilih sejumlah baris menggunakan indeks R untuk baris dan kolom. Ini memungkinkan Anda dengan BERSIH membagi set data yang diberi sejumlah baris - katakan 80% pertama dari data Anda.

Dalam R semua baris dan kolom diindeks sehingga DataSetName [1,1] adalah nilai yang ditetapkan untuk kolom pertama dan baris pertama "DataSetName". Saya dapat memilih baris menggunakan [x,] dan kolom menggunakan [, x]

Sebagai contoh: Jika saya memiliki satu set data yang dinamai "data" dengan 100 baris saya dapat melihat 80 baris pertama menggunakan

Lihat (data [1:80,])

Dengan cara yang sama saya bisa memilih baris ini dan mengelompokkannya menggunakan:

train = data [1:80,]

test = data [81: 100,]

Sekarang saya memiliki data saya dibagi menjadi dua bagian tanpa kemungkinan resampling. Cepat dan mudah.

Dan Butorovich
sumber
1
Meskipun memang benar bahwa data dapat dipisah seperti itu, tidak disarankan. Beberapa dataset dipesan oleh variabel yang tidak Anda sadari. Jadi yang terbaik untuk mengambil sampel baris mana yang akan dianggap sebagai pelatihan alih-alih mengambil baris pertama.
user5029763
1
Jika Anda mengacak data sebelum memisahkannya untuk menguji dan set pelatihan, saran Anda berfungsi.
Hadij