我有一個 6 x 6 網格。我有 36 個樣本,分成三個相等的組別(A、B 和 C)。
我想要一個公式來隨機排列該網格中的樣本。但是,每行和每列必須包含每組中的兩個。手動執行一次或兩次很容易,但有大量的組合。
我對軟體選擇持開放態度,只要它是免費軟體或基於 Microsoft Office 的。
謝謝你!
答案1
我用幾個公式和一些 VBA 組合了一個用於產生隨機行/列排列的工具。工作表佈局如下所示:
參考網格是有效矩陣的一個簡單範例,如加里學生的初步答案中所發布的(可能已被刪除)。行和列排列包含 6x6 網格的所有可能的獨特排列組合。 (如果需要,可以輕鬆修改以包括非唯一排列。)E12:E26
和中的值L12:L26
隨機播種為零或一,以提供是否執行給定排列的基礎。列D
,K
只需將它們轉換為布林值,以簡化 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
上面的程式碼沒有很好地健壯,但可以滿足當前的目的。如果需要的話,擴展/泛化應該非常簡單。特別是,它應該按原樣處理任何大小的二維參考網格,即使是非方形的。關鍵是要確保排列指令數組設定正確。
編輯:經過一番嘗試後,很明顯地該解決方案無法提供對可能排列的全部空間的存取。所以,我通過添加隨機“位移位" 來交換類型標籤。為了簡化操作,我從ABC
標籤切換到123
標籤,這允許透過簡單的MOD
操作來實現,並且還可以以行和列總和的形式進行快速瀏覽健全性檢查:
答案2
有一個非常簡單的方法可以實現這一點。首先預先分配插槽對於這三種類型中的每一種:
然後取出第一個樣本,例如 SAMPLE_A_1,並將其放置在隨機地在 A 槽之一。然後繼續處理剩下的 35 個樣本。
如果這種方法可以接受,我將發布一個簡短的程式來填入矩陣。如果該方法不可接受,我將刪除此帖子。