|
|
|
|
|
|
Excel
|
Function to return random sample, with or without replacement
|
|
Ease of Use
|
Intermediate
|
Version tested with
|
2000, 2002
|
Submitted by:
|
matthewspatrick
|
Description:
|
Function looks at specified range (Source argument) and returns an array of randomly-sampled data from that range. Take argument specifies the number of items in the sample. Optional argument Replacing indicates whether sampling is done with replacement (i.e., any item in the source may be selected more than once, indicated by True) or without replacement (any given item may only be selected once, indicated by False). Optional argument Unique indicates whether the samples are drawn from all items in the Source range (False), or just from the unique elements (True)
|
Discussion:
|
Suppose your VBA sub has to randomly select 100 student test scores from a population of 2000 test scores for statistical summaries?
Or, suppose you have 64 participants signed up for a chess tournament, and they are all entered in an Excel worksheet, and you need a random draw for the first round of 32 matches?
In these or other situations, you need to draw a random sample from a population. This function allows you to define a range holding your population, and then return a randomly selected array of items from that population. You get to choose how many items to draw, whether or not to replace selected items in the population, and whether or not the draw is from the entire population, or just the unique elements of the population.
The function works in both VBA code an worksheets. Keep in mind that you will need to use an array formula if you use this in a worksheet (in conjunction with TRANSPOSE if you want the answers down a column rather than across a row).
|
Code:
|
instructions for use
|
Option Explicit
Function Sample(Source As Range, Take As Long, Optional Replacing As Boolean = False, _
Optional Unique As Boolean = False)
Dim Dict As Object
Dim Coll As Object
Dim xItem As Long
Dim cel As Range
Dim Results()
Dim Counter As Long
Dim xKeys As Variant
Randomize
If Take < 1 Or Take > Source.Cells.Count Then
Sample = CVErr(xlErrValue)
Exit Function
End If
If Unique Then
Set Dict = CreateObject("Scripting.Dictionary")
For Each cel In Source.Cells
If Not Dict.Exists(cel.Value) Then Dict.Add cel.Value, cel.Value
Next
If Take > (UBound(Dict.Keys) + 1) Then
Sample = CVErr(xlErrValue)
Else
For Counter = 1 To Take
If Counter = 1 Then ReDim Results(1 To 1) Else ReDim Preserve Results(1 To Counter)
xKeys = Dict.Keys
xItem = Int(Rnd * (UBound(xKeys) + 1))
Results(Counter) = xKeys(xItem)
If Not Replacing Then Dict.Remove xKeys(xItem)
Next
Sample = Results
End If
Set Dict = Nothing
Else
Set Coll = New Collection
For Each cel In Source.Cells
Coll.Add cel
Next
For Counter = 1 To Take
If Counter = 1 Then ReDim Results(1 To 1) Else ReDim Preserve Results(1 To Counter)
xItem = 1 + Int(Rnd * Coll.Count)
Results(Counter) = Coll(xItem)
If Not Replacing Then Coll.Remove xItem
Next
Sample = Results
Set Coll = Nothing
End If
End Function
|
How to use:
|
- Launch Excel
- Open the workbook you want to add this function to
- Hit Alt-F11 to enter the Visual Basic Editor
- Insert a module into your project, and paste the code into that module
- Close the VB Editor
- Now the function is available to other subs and functions in that workbook's VB Project, or to use in worksheet functions
|
Test the code:
|
- Change examples in the sample file
|
Sample File:
|
Sample.zip 27.09KB
|
Approved by mdmackillop
|
This entry has been viewed 215 times.
|
|