My Problem
I have a huge set of customer data (approx. 100K) with several columns/criteria describing each customer (e.g. age, sex, etc.).
Out of this list I want to generate a random sample of 24K customers that fit a specific distribution.
In this case I need a specific minimum sample size for each criterium, e.g. I need min. 2K cases of customers aged <18, min. 3K cases aged 18-25, etc.
Some of the criteria I draw on are "multiple-choice", e.g. you could be a customer in all 4 possible product segments. Therefore the sample size for those criteria is only minimum not exact (e.g. if you draw 2K cases of product A, you may have already drawn 1K cases of product B users even though I only need 500).
Therefore I need a VBA code that can perform the following:
- Draw a random sample of MAX 24K cases
- Fullfill minimum sample sizes for several criteria (e.g. MIN 2K female customers) if at all possible (e.g. don't produce an error if only 1.9K females are in the sample, instead draw all 1.9K females)
- Cope with multiple-choice criteria by checking before each draw how many samples fullfilling the target criteria are already in the sample (e.g. If I need 2K users of product A, 500 may already be in the sample due to the previous draw of male customers. The code then needs to draw only 1.5K new cases)
Existing code snippet
I found the below code snippet which seems to do some of the stuff I need (draw random samples with a fixed number) but cannot perform the additional checks I need. Also since I do not have a lot of experiences with Dictionaries I do not really know how to adapt the search targets (e.g. instead of "AA"/"BB" in column A, I need "males" in column B, "product A" in column C, etc.)
Option Explicit
'******************************************************
'*** needs reference to Microsoft Scripting Runtime ***
'******************************************************
Sub GetRandomSamples()
Dim oDicSam As Dictionary
Dim iCounter As Integer, k As Variant, iRandom As Integer, iRndMin As Integer, iRndMax As Integer, j As Integer
Dim source As Worksheet, target As Worksheet
On Error GoTo Err_GetRandomSamples
Set source = ThisWorkbook.Worksheets(1)
Set target = ThisWorkbook.Worksheets(2)
'define the range for randomizing
iRndMin = 1
iRndMax = 500
'define the numbers of records for each column
Set oDicSam = New Dictionary
oDicSam.Add "AA", 4
oDicSam.Add "BB", 1
oDicSam.Add "CC", 1
oDicSam.Add "DD", 3
oDicSam.Add "EE", 1
j = 1
Randomize
For Each k In oDicSam.Keys
For iCounter = 1 To oDicSam.Item(k)
iRandom = Int((iRndMax - iRndMin + 1) * Rnd + iRndMin)
'MsgBox "Random number for '" & k & "' is: " & iRandom, vbInformation, "Randomizing - " & iCounter
source.Range(k & iRandom).Copy target.Range("A" & j)
j = j + 1
Next
Next
Exit_GetRandomSamples:
On Error Resume Next
Set source = Nothing
Set target = Nothing
Set oDicSam = Nothing
Exit Sub
Err_GetRandomSamples:
MsgBox Err.Description, vbExclamation, Err.Number
Resume Exit_GetRandomSamples
End Sub
My external thanks
To everyone who can help :)
Aucun commentaire:
Enregistrer un commentaire