data.frame中列顺序的约束随机化

时间:2012-01-24 18:05:19

标签: r random dataframe

我正在尝试从数据框复制每一列,并将其移动到1-3列中随机定位的点,并为数据框中的每一列执行此操作。我希望列向左或向右移动至少一个空格。当然sample(data)随机地重新排序列,但是我试图把它放在一个循环中是非常糟糕的(我承认我跳过了大多数线性代数类,该死的......)。以下是一个示例数据:

dat <- read.table(textConnection(
"-515.5718  94.33423 939.6324 -502.9918 -75.14629 946.6926
-515.2283  96.10239 939.5687 -503.1425 -73.39015 946.6360
-515.0044  97.68119 939.4177 -503.4021 -71.79252 946.6909
-514.7430  99.59141 939.3976 -503.6645 -70.08514 946.6887
-514.4449 101.08511 939.2342 -503.9207 -68.48133 946.7183
-514.2769 102.29453 939.0013 -504.2665 -67.04509 946.7809
-513.9294 104.02753 938.9436 -504.4703 -65.34361 946.7899
-513.5900 105.49624 938.7684 -504.7405 -63.75965 946.7991"
),header=F,as.is=T)
sample(dat)#random columns position

2 个答案:

答案 0 :(得分:3)

这种蛮力但快速解决方案怎么样?

它会尝试列的不同排列,直到找到每列向左或向右移动至少1列,不超过3列的列。当它找到这样的排列时,while()调用的最后一行中的测试将评估为FALSE,终止循环并使变量x包含可接受的排列。

n <- ncol(dat)
while({x <- sample(n)   # Proposed new column positions
       y <- seq_len(n)  # Original column positions
       max(abs(x - y)) > 3 | min(abs(x - y)) == 0
       }) NULL
dat[x]

答案 1 :(得分:1)

我应该等到发布这篇文章,直到我有时间对其进行评论,并讨论上述评论中目前指定的问题中的一些含糊之处。但是由于我无法做到这一点,可能还有一段时间,我想我会给你一个解决方案的代码,你可以自己检查一下。

# Create a function that generates acceptable permutations of the data
getPermutation <- function(blockSize,     # number of columns/block
                           nBlock,        # number of blocks of data
                           fromBlocks) {  # indices of blocks to be moved
    X <- unique(as.vector(outer(fromBlocks, c(-2,-1,1,2), "+")))
    # To remove nonsensical indices like 0 or -1
    X <- X[X %in% seq.int(nBlock)]  

    while({toBlocks <- sample(X, size = length(fromBlocks))  
           max(abs(toBlocks - fromBlocks)) > 2 | min(abs(toBlocks - fromBlocks)) < 1
           }) NULL
    A <- seq.int(nBlock)
    A[toBlocks] <- fromBlocks
    A[fromBlocks] <- toBlocks

    blockColIndices <- 
        lapply(seq.int(nBlock) - 1,
               function(X) {
                   seq(from = X * blockSize + 1, 
                       by = 1, 
                       length.out = blockSize)
               })    
    unlist(blockColIndices[A])
}

# Create an example dataset, a 90 column data.frame
dat <- as.data.frame(matrix(seq.int(90*4), ncol=90))

# Call the function for a data frame with 30 3-column blocks
# within which you want to move blocks 2, 14, and 14.
index <- getPermutation(3, 30, c(2, 14, 15))
newdat <- dat[index]