2013-04-04 58 views
8

我对R相当陌生,但是我做了大量的搜索并没有找到我的问题的答案。r中没有连续的相同数字的采样

我有一个8个位数多次重复一个矢量:

allNum <- c(rep(1, 70), rep(2, 70), rep(3, 35), rep(4, 35), 
      rep(5, 70), rep(6, 70), rep(7, 35), rep(8, 35)) 

现在我想利用这个(可能使用sample(allNum, 420, replace=FALSE))置换,但我不希望任何连续相同数字 - 例如:1 2 2 8

有没有简单的方法来做到这一点?

+0

有点关系:http://stackoverflow.com/questions/14684539/sample-with-a-max/14696912 – 2013-04-04 18:13:13

+0

使用'任何(DIFF(X) == 0)'来检查是否有连续的相同数字?然后继续抽样直到找到一个? – liuminzhao 2013-04-04 18:17:41

+0

什么是可重现的第一个问题! – Gregor 2013-04-04 20:55:46

回答

0

a previous answer借用,一种方法是蛮力并继续采样,直到你得到一个具有所需特性的置换。

nonconsec.permute <- function(pop,size) { 
    while(!exists("x",inherits=FALSE) || 0 %in% diff(x)) { 
    x <- sample(pop, size, replace=F) 
    } 
} 

但是,下面的命令需要很长时间,因为相同的连续数字在您提供的示例中非常常见。所以这种方法在您的具体情况下不可行。

nonconsec.permute(allNum,420) 
3

您有一个问题,即可能随机选择元素,而不是选择受限制的元素。特别是,如果您必须选择的元素数量超过$ 2n-1 $,其中$ n $是最频繁元素出现的次数,您可以选择一个随机元素(与先前的约束一致)。但是,如果这些数字相等,那么对于序列的其余部分,最频繁的值必须位于其他位置(并且可以随机分配值)。认识到这个约束允许一次遍历(没有更多的随机选择,而不是原始向量中的元素)。

permute.nonconsec <- function(allNum) { 
    fully.constrained <- function(x) { 
    2*max(table(x)) - 1 == length(x) 
    } 
    permuted <- numeric(length(allNum)) 
    permuted[1] <- sample(allNum, 1) 
    allNum <- allNum[-min(which(allNum==permuted[1]))] 
    for (i in seq_along(allNum)+1) { 
    if(fully.constrained(allNum)) { 
     # switch to deterministic algorithm 
     # determine which value is the constraining one 
     r <- rle(sort(allNum)) 
     limiter <- r$values[r$lengths==max(r$lengths)] 
     permuted[seq(i, length(permuted), by=2)] <- limiter 
     remaining <- allNum[allNum != limiter] 
     if (length(remaining)>0) { 
     permuted[seq(i+1, length(permuted), by=2)] <- 
      remaining[sample.int(length(remaining))] 
     } 
     break; 
    } 
    available <- allNum[allNum != permuted[i-1]] 
    permuted[i] <- available[sample.int(length(available), 1)] 
    allNum <- allNum[-min(which(allNum==permuted[i]))] 
    } 
    permuted 
} 

如果没有可能的布置这将失败:length(x) < 2 * max(table(x)) - 1,但如果需要可以添加该初始检查。

0

下面是一个简单的算法:

N = 420 
i = as.integer(runif(1, 1, length(allNum))) 
result = allNum[i] 
allNum = allNum[-i] 
while (N != 1) { 
    N = N - 1 

    # pick a random value that's different from last chosen one 
    last = result[length(result)] 
    i = as.integer(runif(1, 1, sum(allNum != last))) 
    result = c(result, allNum[allNum != last][i]) 

    # remove any (doesn't matter which) element of allNum that's 
    # equal to last choice, to sample without replacement 
    last = result[length(result)] 
    allNum = allNum[-which(allNum == last)[1]] 
} 
+0

这个算法的问题是你可以用'allNum'结束包含所有相同的值(比如'allNum = c(2,2)'),在这种情况下它会选择一个2,但接下来会经过, 'sum(allNum!= last)'为0,并且没有可用/有效的值进行采样。 – 2013-04-05 14:55:06

+0

这不是问题。使用该输入和'N = 2'运行算法,您将得到'result = c(2,NA)'。因此,您可以轻松检查您尝试做的采样是否可以实现(并且您还将获得最大可实现的部分)。 – eddi 2013-04-05 15:25:31