固定值不在列和行上重复

Posted

技术标签:

【中文标题】固定值不在列和行上重复【英文标题】:Fixed values not repeated over column and row 【发布时间】:2017-03-20 19:43:18 【问题描述】:

我想在 R 中创建一个包含一组变量(例如 1 到 10)的矩阵。这些变量应该在行和列上随机分配,但不应该在任何一个中重复(所以数字 1 应该在第 1 行一次,在第 1 列一次)!

例如:

1,2,3,4,5,6,7,8,9,10

2,3,4,5,6,7,8,9,10,1

3,4,5,6,7,8,9,10,1,2

4,5,6,7,8,9,10,1,2,3

5,6,7,8,9,10,1,2,3,4

6,7,8,9,10,1,2,3,4,5

7,8,9,10,1,2,3,4,5,6

8,9,10,1,2,3,4,5,6,7

9,10,1,2,3,4,5,6,7,8

10,1,2,3,4,5,6,7,8,9

当然,在那个例子中,数字是递增的,我希望它们随机化。我尝试了简单的矩阵要求,但我无法弄清楚如何做到这一点。任何人都可以帮忙吗?提前致谢!

【问题讨论】:

看起来像一个数独矩阵,你需要一个回溯算法。 【参考方案1】:

除非我误解了这个问题,否则有一种更简单的方法可以创建这个混洗矩阵,无需任何循环或复杂的条件语句。

# number of rows and columns
n <- 10

# create ordered rows and columns
ordered.by.row <- matrix(1:n, n, n)
ordered.by.col <- matrix(1:n, n, n, byrow = T)

# offset the rows and columns relative to each other.
# no row or column has a repeated value, but the values are still ordered
offset <- (ordered.by.row + ordered.by.col) %% n + 1

# shuffle the columns, then shuffle the rows, this produces a randomized matrix
# 'shuffle.row' is the final, randomized matrix
set.seed(1222) # change this to change randomization
shuffle.col <- offset[,sample(1:n, n, replace = F)]
shuffle.row <- shuffle.col[sample(1:n, n, replace = F), ]

# verify solution
any(apply(shuffle.row, 1, function(r)any(duplicated(r)))) # FALSE
any(apply(shuffle.row, 2, function(r)any(duplicated(r)))) # FALSE

      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    1   10    6    9    2    8    3    5    7     4
 [2,]    3    2    8    1    4   10    5    7    9     6
 [3,]    7    6    2    5    8    4    9    1    3    10
 [4,]    9    8    4    7   10    6    1    3    5     2
 [5,]   10    9    5    8    1    7    2    4    6     3
 [6,]    2    1    7   10    3    9    4    6    8     5
 [7,]    8    7    3    6    9    5   10    2    4     1
 [8,]    6    5    1    4    7    3    8   10    2     9
 [9,]    5    4   10    3    6    2    7    9    1     8
[10,]    4    3    9    2    5    1    6    8   10     7

【讨论】:

洗牌会保持随机化吗?这肯定比回溯快得多。 是的。在两个单独的步骤中执行随机化是关键。首先,我们创建“有序解决方案”,其中每个数字在每一行和每一列中出现一次,但所有数字仍然是有序的。当我们随机化列时,我们仍然满足行的唯一性标准。然后我们随机化行,并且仍然满足列的唯一性。当然,打乱后的行和列索引是随机选择的,因此保留了随机性。 这太完美了!非常感谢! 再次感谢您过去的回答!现在我有一个稍微不同的问题(不确定我是否应该打开另一个问题..)。不同之处在于:我的样本中有一半是预先给出的,需要保持原样(比如说第 1 到第 5 行)。我仍然需要对另一行(6-10)进行随机化,没有任何行或列重复。更准确地说:我有 5 行,例如上面的示例 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [1 ,] 1 10 6 9 2 8 3 5 7 4 [2,] 3 2 8 1 4 10 5 7 9 6 [3,] 7 6 2 5 8 4 9 1 3 10 [4,] 9 8 4 7 10 6 1 3 5 2 [5,] 10 9 5 8 1 7 2 4 6 3【参考方案2】:

这看起来就像生成一个Sudoku 网格。下面的代码运行得很快,但可以做一些小的R 优化:

backtrack = function(n = 10)
  x = matrix(NA, ncol = n, nrow = n)
  cells = list()
  k = 1
  for (i in 1:n)
    for (j in 1:n)
      cells[[k]] = sample(1:n)
      k = k + 1
    
  

  i = 0
  while (i < n*n)
    candidates = cells[[i + 1]]
    idx = sample(1:length(candidates), 1)
    val = candidates[idx]

    if (length(candidates) == 0)
      cells[[i + 1]] = sample(1:n)
      i = i - 1
      x[as.integer(i/n) + 1,  i %% n + 1] = NA
    
    else 
      rr = as.integer(i/n) + 1
      cc = i %% n + 1
      if ((val %in% x[rr, ]) || (val %in% x[, cc]))
        candidates = candidates[-idx]
        cells[[i + 1]] = candidates
      
      else
        x[as.integer(i/n) + 1, i %% n + 1] = val
        candidates = candidates[-idx]
        cells[[i + 1]] = candidates
        i = i + 1
      
    
  
  x

测试:

set.seed(1) # Please change this
x = backtrack(10)
print(x)

      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    8   10    4    6    9    7    1    2    3     5
 [2,]    5    6    9    8    1   10    4    3    2     7
 [3,]   10    7    1    2    8    9    5    4    6     3
 [4,]    3    9    8   10    6    5    7    1    4     2
 [5,]    9    1    6    4    7    3    2    5   10     8
 [6,]    1    4   10    3    2    6    8    7    5     9
 [7,]    2    8    5    9   10    1    3    6    7     4
 [8,]    6    5    2    7    3    4   10    9    8     1
 [9,]    4    3    7    1    5    2    6    8    9    10
[10,]    7    2    3    5    4    8    9   10    1     6


any(apply(x, 1, function(r)any(duplicated(r)))) # FALSE
any(apply(x, 2, function(r)any(duplicated(r)))) # FALSE

【讨论】:

哇!非常感谢你,@费尔南多!!!这正是我所需要的(尽管我可能需要一段时间才能真正理解你做了什么;))!! 不客气。这是一个回溯算法:en.wikipedia.org/wiki/Backtracking 您可以接受答案或等待更多人输入。通常你应该稍等片刻,但在这种情况下,除了回溯之外,我没有看到任何解决方案。 嗨费尔南多!对于您回答的问题,我还有一个问题:当我已经修复了前 3 行时,如何调整回溯?我认为这适用于回溯,但我无法管理...... 第一行例如这样:row1

以上是关于固定值不在列和行上重复的主要内容,如果未能解决你的问题,请参考以下文章

删除熊猫数据框中包含特定值的列和行[重复]

在 gsheet 中的特定列和行上添加时间戳并冻结列

Pandas列表的列,通过迭代(选择)三列的每个列表元素作为新列和行来创建多列[重复]

Pandas 数据框:按列和行替换值的性能是不是有差异?

从 PySpark 中的选定列和行中提取值

Flex 具有一个固定宽度的列和一个必须填充剩余空间的流体列[重复]