【问题标题】:Constrained randomization of column order in a data.framedata.frame 中列顺序的约束随机化
【发布时间】:2012-02-17 23:47:45
【问题描述】:

我正在尝试复制数据框中的每一列并将其移动到 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

【问题讨论】:

    标签: r random dataframe


    【解决方案1】:

    这个蛮力但非常快速的解决方案怎么样?

    它会尝试不同的列排列,直到找到每列至少移动 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]
    

    【讨论】:

    • 我无法确定您是否还要确保每一列至少向左或向右移动一个空格。但是,如果是这种情况,扩展此代码以涵盖添加的条件应该很容易;)
    • 是的,我希望他们至少向左或向右移动一个空格 - 添加到说明中。
    • @GeekOnAcid -- 很好。我已经对其进行了编辑以测试这两个条件,并继续循环,直到找到符合这两个条件的排列。
    • 谢谢,这是一个很棒的小循环。只是一个问题,如果您不介意 - 您将如何修改此循环以使用相同的模式移动 2 个连续的列而不是 1 个?
    • @GeekOnAcid -- 你能用列索引告诉我你的意思吗?例如,运行上面的代码,我得到了这个排列:2 1 4 3 6 5。你想让所有对 (list(c(1,2), c(3,4), c(5,6))) 像块一样移动吗?您是否只想移动随机确定的一对,与另一对交换位置?如果您列出一些您所追求的排列类型的示例,我将有更好的机会提供帮助。谢谢!
    【解决方案2】:

    我可能应该等到有时间发表评论后再发布,并讨论上面 cmets 中当前指定的问题中的一些歧义。但由于我无法做到这一点,可能有一段时间,我想我会给你一个解决方案的代码,你可以自己检查。

    # 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]
    

    【讨论】:

      猜你喜欢
      • 2011-09-05
      • 1970-01-01
      • 1970-01-01
      • 2019-08-17
      • 2020-06-15
      • 2022-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多