Tenga cuidado samplecon la división si busca resultados reproducibles. Si sus datos cambian aunque sea ligeramente, la división variará incluso si la usa set.seed. Por ejemplo, imagine que la lista ordenada de ID en sus datos es todos los números entre 1 y 10. Si acaba de dejar una observación, digamos 4, el muestreo por ubicación produciría resultados diferentes porque ahora 5 a 10 todos los lugares movidos.
Un método alternativo es usar una función hash para asignar ID a algunos números pseudoaleatorios y luego muestrear el mod de estos números. Esta muestra es más estable porque la asignación ahora está determinada por el hash de cada observación, y no por su posición relativa.
Por ejemplo:
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
el tamaño de la muestra no es exactamente 5000 porque la asignación es probabilística, pero no debería ser un problema en muestras grandes gracias a la ley de los números grandes.
Ver también: http://blog.richardweiss.org/2016/12/25/hash-splits.html
y /crypto/20742/statistical-properties-of-hash-functions-when -cálculo-módulo
xpuede ser el índice (fila / col nos. decir) de sudata.sizepuede ser0.75*nrow(data). Intentasample(1:10, 4, replace = FALSE, prob = NULL)ver qué hace.