带有警告/标准的随机选择

带有警告/标准的随机选择

我有一个 6 x 6 的网格。我将 36 个样本分成三组(A、B 和 C)。

我想要一个公式来随机排列网格中的样本。但是每行和每列必须包含每个组的两个样本。手动执行一两次很容易,但组合数量却非常多。

我对软件的选择持开放态度,只要它是免费软件或基于 Microsoft Office 的。

谢谢你!

答案1

我使用几个公式和一些 VBA 制作了一个用于生成随机行/列排列的工具。工作表布局如下所示:

Excel 片段

参考网格是一个有效矩阵的简单示例,如 Gary 学生的初步答案中所述(可能已被删除)。行和列排列包含 6x6 网格的所有可能的唯一排列组合。 (如果需要,可以轻松修改以包括非唯一排列。)和中的值E12:E26随机L12:L26播种为零或一,以提供是否执行给定排列的基础。列DK只是将它们转换为布尔值以简化 VBA 中的处理(见下文)。排列网格由自定义函数生成doSwap,作为数组公式输入。按下F9触发工作表重新计算会导致各种RAND函数重新生成其随机值,从而更改要执行的排列系列。

实现此行为的 VBA 代码是:

Function doSwap(srcRg As Range, rowSwaps As Range, colSwaps As Range) As Variant
    Dim workVt As Variant
    Dim iter As Long

    workVt = srcRg.Value

    ' Do row swaps
    For iter = 1 To rowSwaps.Rows.Count
        With rowSwaps
            If .Cells(iter, 3).Value Then
                workVt = swapRow(workVt, .Cells(iter, 1), .Cells(iter, 2))
            End If
        End With
    Next iter

    ' Do col swaps
    For iter = 1 To colSwaps.Rows.Count
        With colSwaps
            If .Cells(iter, 3).Value Then
                workVt = swapCol(workVt, .Cells(iter, 1), .Cells(iter, 2))
            End If
        End With
    Next iter

    ' Store and return
    doSwap = workVt

End Function

Function swapCol(ByVal inArr As Variant, idx1 As Long, idx2 As Long) As Variant
    Dim tempVal As Variant, workVt As Variant
    Dim iter As Long

    ' Check if Range or Array input
    If IsObject(inArr) Then
        If TypeOf inArr Is Range Then
            workVt = inArr.Value
        Else
            swapCol = "ERROR"
            Exit Function
        End If
    Else
        workVt = inArr
    End If

    ' Just crash if not correct size
    ' Do swap
    For iter = LBound(workVt, 1) To UBound(workVt, 1)
        tempVal = workVt(iter, idx1)
        workVt(iter, idx1) = workVt(iter, idx2)
        workVt(iter, idx2) = tempVal
    Next iter

    ' Return
    swapCol = workVt

End Function

Function swapRow(ByVal inArr As Variant, idx1 As Long, idx2 As Long) As Variant
   Dim tempVal As Variant, workVt As Variant
   Dim iter As Long

    ' Check if Range or Array input
    If IsObject(inArr) Then
        If TypeOf inArr Is Range Then
            workVt = inArr.Value
        Else
            swapRow = "ERROR"
            Exit Function
        End If
    Else
        workVt = inArr
    End If

    ' Just crash if not correct size
    ' Do swap
    For iter = LBound(workVt, 2) To UBound(workVt, 2)
        tempVal = workVt(idx1, iter)
        workVt(idx1, iter) = workVt(idx2, iter)
        workVt(idx2, iter) = tempVal
    Next iter

    ' Return
    swapRow = workVt

End Function

上述代码的鲁棒性不是很好,但可以满足当前目的。如果需要,扩展/泛化应该非常简单。特别是,它应该可以按原样处理任何大小的 2-D 参考网格,即使是非正方形的网格。关键是确保正确设置排列指令数组。

编辑:玩了一会儿之后,很明显这个解决方案无法提供对可能排列的完整空间的访问。因此,我通过添加一个随机“移位“在它们之间交换类型标签。为了简化事情,我从ABC标签切换到123标签,这允许通过简单的MOD操作实现,并且还可以以行和列总和的形式快速检查完整性:

Excel 片段

答案2

有一个非常简单的方法可以实现这一点。首先预先分配插槽以下三种类型均适用:

在此处输入图片描述

然后取第一个样本,例如 SAMPLE_A_1,并将其放置在随机在其中一个 A 槽中。然后继续处理剩余的 35 个样本。


如果这种方法可以接受,我将发布一个简短的程序来填充矩阵。如果这种方法不可接受,我将删除此帖子。

相关内容