РЕДАКТИРОВАТЬ:
На основе комментариев после исходного вопроса, вы можете просто сделать:
my.sample <- function(x,n){
samples <- rle(List)$lengths
ng <- length(samples)
groups <- cut(1:ng,n,labels=FALSE)
reps <- tapply(samples,groups,sum)
rep(1:n,reps)
}
> my.sample(List,4)
[1] 1 1 1 1 2 2 3 3 3 3 4 4 4
, чтобы получить вектор, который вы можете использовать в split()
.
Проблемы возникают, если вы начинаете иметь векторы, подобные c (1,1,1,1,1,1,1,1,1,2,2,3,3,4,4).Если вы не возражаете против порядка смещения, вы можете построить для него функцию, основанную на следующей логике:
- разделить вектор на список векторов уникальных значений
- объедините их в n групп
- пройдитесь по n группам и проверьте, все ли они - больше или меньше равной длины.Если нет, переключите одно значение с самого большого на самое маленькое.
- продолжайте, пока разница не станет меньше, чем модуль общей длины и количества групп, или вы запустили алгоритм, скажем, 10 раз (вв некоторых крайних случаях вы можете получить бесконечный цикл while)
Это дает следующую функцию
my.sample <- function(x,n){
# these are the unique values from which to sample
samples <- split(x,x)
ns <- length(samples)
groups <- list()
# make sure that sample() returns n groups
while(length(groups)!=n){
groups <- split(samples,sample(1:n,ns,replace =TRUE))
}
count <- 0
lgroups <- c(1,ns)
while(diff(range(lgroups)) > ns%%n & count < 10 ){
lgroups <- sapply(groups,function(i)length(unlist(i))) # length of groups
ngroups <- sapply(groups,length) # number of unique values
id <- which(ngroups > 1) # which groups have more than one unique value
#switch one value from the largest to the smallest group
gmin <- which.min(lgroups)
gmax <- id[which.max(lgroups[id])]
gsw <- sample(1:length(groups[gmax]),1)
groups[[gmin]] <- c(groups[[gmin]],groups[[gmax]][gsw])
groups[[gmax]] <- groups[[gmax]][-gsw]
count <- count+1
}
# create the output
lapply(groups,unlist,use.names=FALSE)
}
Может применяться следующим образом:
> my.sample(List,4)
$`1`
[1] 5 5 5 5
$`2`
[1] 11 11 2
$`3`
[1] 3 3 9
$`4`
[1] 1 1 1
Он все еще может быть настроен на ваши собственные нужды, но это похоже на R-подобный способ сделать это.