Méfiez-vous du sample
fractionnement si vous recherchez des résultats reproductibles. Si vos données changent même légèrement, la répartition variera même si vous utilisez set.seed
. Par exemple, imaginez que la liste triée des identifiants dans vos données contient tous les nombres entre 1 et 10. Si vous venez de supprimer une observation, disons 4, l'échantillonnage par emplacement donnerait des résultats différents car maintenant 5 à 10 tous les lieux ont été déplacés.
Une méthode alternative consiste à utiliser une fonction de hachage pour mapper les identifiants en certains nombres pseudo aléatoires, puis à échantillonner sur le mod de ces nombres. Cet échantillon est plus stable car l'affectation est désormais 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] 5 000
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'assignation est probabiliste, mais elle ne devrait pas poser de problème dans les grands échantillons grâce à la loi des grands nombres.
Voir également: http://blog.richardweiss.org/2016/12/25/hash-splits.html
et /crypto/20742/statistical-properties-of-hash-functions-when -calculer-modulo
x
peut être l'index (ligne / col nos. dire) de votredata
.size
peut être0.75*nrow(data)
. Essayezsample(1:10, 4, replace = FALSE, prob = NULL)
de voir ce qu'il fait.