在我的心理学实验中,我有一个词刺激的配价类别。1 =负极,2 =中性,3 =正极我需要用伪随机条件对成千上万的刺激进行排序。瓦尔_Category在一行中不能有2个以上的相同效价刺激,即连续不超过2次负刺激。例如-2,2,2 =不可接受2、2、1 =正常我无法对数据进行排序。决定整个实验的结果是1,3,2,3,1,3,2,3,2,2,1因为我不允许有一个模式。我尝试了各种软件包,如dylpr,样品,订单,排序和没有任何到目前为止解决问题。
oknwwptz1#
我认为有一千种方法可以做到这一点,没有一种可能是非常漂亮的。我写了一个小函数来处理排序。这是一个有点黑客,但它似乎为我所尝试的工作。为了解释我所做的,该函数的工作原理如下:1.取化合价的向量和样本。1.如果发现序列大于所需长度,则(对于每个这样的序列),取该序列在“其他地方”的最后一个值。1.检查问题是否解决。如果是,返回重新排序的向量。如果没有,那就回到2。
# some vector of valencesval <- 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}
# 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
# return the reordered sequence
out
示例:
该函数可用于带或不带名称的向量。如果向量被命名,则这些名称将仍然存在于伪随机化向量上。
# simple unnamed vectorval <- 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 vectornames(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
# 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)
# 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
此属性可用于随机化整个 Dataframe 。为了实现这一点,从 Dataframe 中取出“价”向量,并通过行索引(1:nrow(dat))或行名称(rownames(dat))为其分配名称。
1:nrow(dat)
rownames(dat)
# reorder a data.frame using a named vectordat <- data.frame(val=rep(1:3,each=5), stim=rep(letters[1:5],3))val <- dat$valnames(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# ...
# 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)),]
# val stim
# 5 1 e
# 2 1 b
# 9 2 d
# 6 2 a
# 3 1 c
# 15 3 e
# ...
dm7nw8vv2#
我相信这个循环会适当地设置化合价类别。我把化合价分类称为治疗。
#Generate example datas1 = data.frame(id=c(1:10),treat=NA)#Setting the first two rowss1[1,"treat"] <- sample(1:3,1)s1[2,"treat"] <- sample(1:3,1)#Looping through the remainder of the rowsfor (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) }}
#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)
这个解决方案并不是特别优雅。可能有一个更快的方法来完成这一点,通过排序几列或其他东西。
2条答案
按热度按时间oknwwptz1#
我认为有一千种方法可以做到这一点,没有一种可能是非常漂亮的。我写了一个小函数来处理排序。这是一个有点黑客,但它似乎为我所尝试的工作。
为了解释我所做的,该函数的工作原理如下:
1.取化合价的向量和样本。
1.如果发现序列大于所需长度,则(对于每个这样的序列),取该序列在“其他地方”的最后一个值。
1.检查问题是否解决。如果是,返回重新排序的向量。如果没有,那就回到2。
示例:
该函数可用于带或不带名称的向量。如果向量被命名,则这些名称将仍然存在于伪随机化向量上。
此属性可用于随机化整个 Dataframe 。为了实现这一点,从 Dataframe 中取出“价”向量,并通过行索引(
1:nrow(dat)
)或行名称(rownames(dat)
)为其分配名称。dm7nw8vv2#
我相信这个循环会适当地设置化合价类别。我把化合价分类称为治疗。
这个解决方案并不是特别优雅。可能有一个更快的方法来完成这一点,通过排序几列或其他东西。