2015-07-25 5 views
1

У меня есть категория Valence для стимулов слова в моем эксперименте психологии.«Случайный» Сортировка с условием в R для исследования психологии

1 = Отрицательное, 2 = нейтральной, 3 = Положительный

Мне нужно сортировать тысячи раздражителей с псевдо-рандомизированного состоянием.

Val_Category не может иметь более 2 одинаковых валентных стимулов подряд, то есть не более 2x отрицательных стимулов в строке.

, например - 2, 2, 2 = не приемлемо

2, 2, 1 = нормально

Я не могу последовательности данных, т.е. решить весь эксперимент будет 1,3,2, 3,1,3,2,3,2,2,1, потому что мне не разрешено иметь образец.

Я пробовал различные пакеты, такие как dylpr, sample, order, sort и ничего до сих пор решает проблему.

ответ

0

Я думаю, что существует тысяча способов сделать это, ни одна из которых, вероятно, очень красивая. Я написал небольшую функцию, которая заботится о заказе. Это немного хаки, но, похоже, он работал на то, что я пробовал.

Чтобы объяснить, что я сделал, функция работает следующим образом:

  1. Возьмите вектор валентности и образцов из него.
  2. Если найдены последовательности, которые больше желаемой длины, то (для каждой такой последовательности) берут последнее значение этой последовательности в местах, где это «где-то еще».
  3. Проверьте, не решена ли проблема. Если это так, верните переупорядоченный вектор. Если нет, то вернитесь к 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 
# ... 
+0

Wow Thanks! Этот код немного выше моей головы. Можно ли прокомментировать каждую строку, объясняя, что она делает, чтобы я мог объяснить это моему руководителю? – user4388690

+0

Я добавил дополнительные комментарии к соответствующим строкам кода. Помогает ли это? – SimonG

+1

Да, это огромная помощь! Я пытаюсь выяснить, как вывести полный кадр данных с моими другими столбцами «Word, Wd_ID, Test, Set» в порядке? Как мне это сделать? – user4388690

0

Я считаю, что этот цикл установит категорию Valence соответствующим образом. Я назвал валентные категории лечить.

#Generate example data 
s1 = data.frame(id=c(1:10),treat=NA) 

#Setting the first two rows 
s1[1,"treat"] <- sample(1:3,1) 
s1[2,"treat"] <- sample(1:3,1) 

#Looping through the remainder of the rows 
for (i in 3:length(s1$id)) 
{ 
    s1[i,"treat"] <- sample(1:3,1) 

    #Check if the treat value is equal to the previous two values. 
    if (s1[i,"treat"]==s1[i-1,"treat"] & s1[i-1,"treat"]==s1[i-2,"treat"]) 

    #If so draw one of the values not equal to that value 
    { 
     a = 1:3 
     remove <- s1[i,"treat"] 
     a=a[!a==remove] 
     s1[i,"treat"] <- sample(a,1) 
    } 
} 

Это решение не особенно элегантно. Может быть гораздо более быстрый способ выполнить это путем сортировки нескольких столбцов или чего-то еще.

+0

Проблема может заключаться в том, что пользователь не может контролировать сбор полученного вектора валентности. Случайно, какое-то условие валентности могло просто исчезнуть из экспримента. – SimonG

+0

@SimonG Согласен, хотя это будет проблемой только с очень маленьким образцом (и поскольку я привел пример N = 10, точка хорошо взята). – user3055034