Я думаю, что существует тысяча способов сделать это, ни одна из которых, вероятно, очень красивая. Я написал небольшую функцию, которая заботится о заказе. Это немного хаки, но, похоже, он работал на то, что я пробовал.
Чтобы объяснить, что я сделал, функция работает следующим образом:
- Возьмите вектор валентности и образцов из него.
- Если найдены последовательности, которые больше желаемой длины, то (для каждой такой последовательности) берут последнее значение этой последовательности в местах, где это «где-то еще».
- Проверьте, не решена ли проблема. Если это так, верните переупорядоченный вектор. Если нет, то вернитесь к 2.
# some vector of valences
val <- rep(1:3,each=50)
pseudoRandomize <- function(x, n){
# take an initial sample
out <- sample(val)
# check if the sample is "bad" (containing sequences longer than n)
bad.seq <- any(rle(out)$lengths > n)
# length of the whole sample
l0 <- length(out)
while(bad.seq){
# get lengths of all subsequences
l1 <- rle(out)$lengths
# find the bad ones
ind <- l1 > n
# take the last value of each bad sequence, and...
for(i in cumsum(l1)[ind]){
# take it out of the original sample
tmp <- out[-i]
# pick new position at random
pos <- sample(2:(l0-2),1)
# put the value back into the sample at the new position
out <- c(tmp[1:(pos-1)],out[i],tmp[pos:(l0-1)])
}
# check if bad sequences (still) exist
# if TRUE, then 'while' continues; if FALSE, then it doesn't
bad.seq <- any(rle(out)$lengths > n)
}
# return the reordered sequence
out
}
Пример:
Функция может быть использована на векторе с или без имен. Если бы вектор был назван, то эти имена будут по-прежнему присутствовать на псевдо-рандомизированном векторе.
# simple unnamed vector
val <- rep(1:3,each=5)
pseudoRandomize(val, 2)
# gives:
# [1] 1 3 2 1 2 3 3 2 1 2 1 3 3 1 2
# when names assigned to the vector
names(val) <- 1:length(val)
pseudoRandomize(val, 2)
# gives (first row shows the names):
# 1 13 9 7 3 11 15 8 10 5 12 14 6 4 2
# 1 3 2 2 1 3 3 2 2 1 3 3 2 1 1
Это свойство может использоваться для случайного распределения всего кадра данных. Для этого вектор валентности извлекается из кадра данных, а имена присваиваются ему либо индексом строки (1:nrow(dat)
), либо именами строк (rownames(dat)
).
# reorder a data.frame using a named vector
dat <- data.frame(val=rep(1:3,each=5), stim=rep(letters[1:5],3))
val <- dat$val
names(val) <- 1:nrow(dat)
new.val <- pseudoRandomize(val, 2)
new.dat <- dat[as.integer(names(new.val)),]
# gives:
# val stim
# 5 1 e
# 2 1 b
# 9 2 d
# 6 2 a
# 3 1 c
# 15 3 e
# ...
Wow Thanks! Этот код немного выше моей головы. Можно ли прокомментировать каждую строку, объясняя, что она делает, чтобы я мог объяснить это моему руководителю? – user4388690
Я добавил дополнительные комментарии к соответствующим строкам кода. Помогает ли это? – SimonG
Да, это огромная помощь! Я пытаюсь выяснить, как вывести полный кадр данных с моими другими столбцами «Word, Wd_ID, Test, Set» в порядке? Как мне это сделать? – user4388690