web-dev-qa-db-fra.com

Comment fractionner des données en ensembles de formation/test à l'aide de la fonction exemple

Je viens de commencer à utiliser R et je ne sais pas comment incorporer mon ensemble de données avec l'exemple de code suivant: 

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

J'ai un ensemble de données que je dois mettre dans un ensemble de formation (75%) et de test (25%) ... Je ne suis pas sûr des informations que je suis censé mettre dans le x et dans la taille? x le fichier de jeu de données et la taille de mes échantillons? 

124
Susie Humby

Il existe de nombreuses approches pour réaliser le partitionnement des données. Pour une approche plus complète, jetez un œil à la fonction createDataPartition du paquet caret.

Voici un exemple simple:

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

Cela peut être facilement fait par:

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

En utilisant caTools package:

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

C'est presque le même code, mais en plus Nice look

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
26
Katrina Malakhova

Je voudrais utiliser dplyr pour cela, le rend super simple. Cela nécessite une variable id dans votre ensemble de données, ce qui est une bonne idée, non seulement pour créer des ensembles, mais également pour la traçabilité pendant votre projet. Ajoutez-le si ne contient pas déjà.

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

Je vais séparer 'a' entre train (70%) et test (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,]

terminé

18
hyunwoo jeong
library(caret)
intrain<-createDataPartition(y=sub_train$classe,p=0.7,list=FALSE)
training<-m_train[intrain,]
testing<-m_train[-intrain,]
17
pradnya chavan

Ma solution est fondamentalement la même que celle de dickoa mais un peu plus facile à interpréter:

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

Juste une manière plus brève et simple d’utiliser awesome dplyr library:

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, ]
5
SHi ON

Si vous tapez: 

?sample

If lancera un menu d'aide pour expliquer la signification des paramètres de la fonction exemple. 

Je ne suis pas un expert, mais voici un code que j'ai:

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

Cela vous donnera 75% de train et 25% de test.

5
user2502836

Ma solution mélange les lignes, prend ensuite 75% des lignes comme train et les 25% restants comme test. Super simples!

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

Ci-dessous une fonction qui crée unelist de sous-échantillons de la même taille qui n'est pas exactement ce que vous vouliez, mais qui pourrait s'avérer utile pour d'autres Dans mon cas, créer plusieurs arbres de classification sur des échantillons plus petits pour tester le surajustement:

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

Exemple :

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

Utiliser le paquetage caTools dans le code d’exemple R .__ sera comme suit: -

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

Utilisez la base R. La fonction runif génère des valeurs uniformément réparties de 0 à 1. En modifiant la valeur limite (train.size, dans l'exemple ci-dessous), vous aurez toujours à peu près le même pourcentage d'enregistrements aléatoires en dessous de la valeur limite.

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

Je suis tombé sur celui-ci, ça peut aider aussi.

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
user322203

Le package scorecard a une fonction utile pour cela, où vous pouvez spécifier le ratio et le germe

library(scorecard)

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

Les données de test et de train sont stockées dans une liste et sont accessibles en appelant dt_list$train et dt_list$test.

1
camnesia
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)

La fonction sample.split() ajoutera une colonne supplémentaire 'split1' à la structure de données et 2/3 des lignes auront la valeur TRUE et les autres FALSE. test dataframe.

1
Abhishek

Je peux suggérer d'utiliser le package 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)
1
igoR87

En supposant que df est votre bloc de données et que vous souhaitez créer 75% train et 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]

Ensuite, pour créer un train et tester des trames de données

df_train <- df[train_i,]
df_test <- df[test_i,]
1
Corentin
set.seed(123)
llwork<-sample(1:length(mydata),round(0.75*length(mydata),digits=0)) 
wmydata<-mydata[llwork, ]
tmydata<-mydata[-llwork, ]
0
Xavier Jiménez

Après avoir examiné toutes les méthodes décrites ici, je n'ai vu personne utiliser TRUE/FALSE pour sélectionner et désélectionner des données. J'ai donc pensé partager une méthode utilisant cette technique.

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

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

Explication

Il existe plusieurs façons de sélectionner des données à partir de R; le plus souvent, les utilisateurs utilisent des indices positifs/négatifs pour sélectionner/désélectionner, respectivement. Cependant, les mêmes fonctionnalités peuvent être obtenues en utilisant TRUE/FALSE pour sélectionner/désélectionner.

Prenons l'exemple suivant.

# 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
0
Joe

Méfiez-vous de sample pour la division si vous recherchez des résultats reproductibles. Si vos données changent même légèrement, la division variera même si vous utilisez set.seed. Par exemple, imaginez que la liste triée des identifiants dans vos données se compose de tous les nombres compris entre 1 et 10. Si vous venez de supprimer une observation, disons 4, l'échantillonnage par emplacement produirait un résultat différent, car maintenant, 5 à 10 lieux ont été déplacés. 

Une autre méthode consiste à utiliser une fonction de hachage pour mapper les identifiants dans des nombres pseudo aléatoires, puis échantillonner sur le mod de ces nombres. Cet échantillon est plus stable car l'attribution est maintenant déterminée par le hachage de chaque observation et non par sa position relative.

Par exemple:

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

la taille de l'échantillon n'est pas exactement de 5000 car l'attribution est probabiliste, mais cela ne devrait pas être un problème dans les grands échantillons grâce à la loi des grands nombres.

Voir aussi: http://blog.richardweiss.org/2016/12/25/hash-splits.html Et https://crypto.stackexchange.com/questions/20742/statistical- propriétés-de-fonctions de hachage lors du calcul modulo

0
dzeltzer