简体   繁体   English

VBA脚本中使用“数据分析工具”产生的随机数生成器错误

[英]Random-Number-Generator Error from “Data Analysis Tool” use in VBA script

I have created a VBA script which performs the statistical technique bootstrapping. 我创建了一个执行统计技术自举的VBA脚本。 My original sample is drawn from a Poisson distribution through the use of the Data Analysis Tool in excel (as there is no inverse build in excel function for Poisson distribution and I cannot think of any other way of simulating values from a Poisson distribution). 我的原始样本是通过使用excel中的数据分析工具从Poisson分布中提取的(因为Poisson分布的excel函数没有逆向构建,因此我无法想到任何其他方法来模拟Poisson分布的值)。 However when I run my VBA script, I got this notification from its first iteration: 但是,当我运行VBA脚本时,我从第一次迭代中得到了此通知:

"Random Number Generation-Outputs range will overwrite existing data. Press OK to overwrite data in range:'[TestCoverage(Poisson,ss50).xlsm]ParametricBootstrap'!$B$2:$B$51" “随机数生成-输出范围将覆盖现有数据。按OK即可覆盖范围内的数据:'[TestCoverage(Poisson,ss50).xlsm] ParametricBootstrap'!$ B $ 2:$ B $ 51”

I am aware of the "overwriting" demand when the Data Analysis Tool is used and for that reason I always check that the cells are empty before I operate the VBA script. 我知道使用数据分析工具时的“覆盖”需求,因此,在操作VBA脚本之前,我总是检查单元格是否为空。 But apart from checking myself that they are clear, I have incorporated in the model a specific part for clearing the contents of the cells that the problem is indicated in, just before the first time the Tool is used (line16), but still the VBA script acts like the cells are not empty showing this notification. 但是除了检查自己是否清楚之外,我还在模型中加入了一个特定部分,用于清除指示问题所在的单元格的内容,就在第一次使用此工具之前(第16行),但仍然是VBA脚本的行为就像显示此通知的单元格不为空。 By the time the VBA script reaches line22 (the operation of the Data Analysis Tool) it throws the previous message. 当VBA脚本到达第22行(​​数据分析工具的操作)时,它将引发前一条消息。

The peculiar part is that I have created an identical VBA script (as I have to evaluate bootstrapping for a pool of distributions) which draws the original sample from a Normal distribution, again with the use of the Data Analysis Tool, but in that case it operates normally. 特殊的部分是,我创建了一个相同的VBA脚本(因为我必须评估分发池的引导程序),该脚本再次使用数据分析工具从正态分布中提取原始样本,但在这种情况下,运行正常。

This is the code: 这是代码:

Sub parametricbootstrappoisson50()

Dim iterations As Integer

iterations = InputBox("Please insert the number of times you want the bootstrapping process to be performed")

Application.ScreenUpdating = False

'These statements clear the results in the Coverage Results sheet existing from previous operations of the macro
Sheets("Coverage Results").Activate
Range("A3").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.ClearContents
Sheets("Parametric Bootstrap").Activate
Range("B2:C51").Select
Selection.ClearContents

For n = 1 To iterations

    'Creates an original sample from a Poisson distribution with parameter lambda P2 (mean)
    Application.Run "ATPVBAEN.XLAM!Random", ActiveSheet.Range("$B$2"), 1, 50, _
    5, , Range("P2").Value

    '1000 bootstrap samples and bootstrap means are produced and stored in the respective cells

    For i = 1 To 1000

        'Creates a bootstrap sample from a Poisson distribution with estimated parameter lambda Q2 (mean)
        Application.Run "ATPVBAEN.XLAM!Random", ActiveSheet.Range("$B$2"), 1, 50, _
        5, , Range("Q2").Value
        Sheets("Parametric Bootstrap").Range("E2").Offset(i, 0).Value = Sheets("Parametric Bootstrap").Range("R2").Value

        'Delete the bootstrap sample produced so that it will not need confirmation to overwrite the data when the next bootstrap sample will be drawn
        Range("C2:C51").Select
        Selection.ClearContents

    Next i

    'This is the process of transferring the results of the bootstrapping process to the Coverage Results sheet
    Sheets("Coverage Results").Range("A1:F1").Offset(n, 0).Value = Sheets("Parametric Bootstrap").Range("I2:N2").Value

    'Indication on whether the population mean is covered from the bootstrap confidence intervals of the nth iteration or not
    If Sheets("Parametric Bootstrap").Range("P2").Value >= Sheets("Coverage Results").Range("C1").Offset(n, 0).Value And Sheets("Parametric Bootstrap").Range("P2").Value <= Sheets("Coverage Results").Range("D1").Offset(n, 0).Value Then
        Sheets("Coverage Results").Range("G1").Offset(n, 0).Value = "Yes"
    Else
        Sheets("Coverage Results").Range("G1").Offset(n, 0).Value = "No"
    End If

    Sheets("Parametric Bootstrap").Activate

    'Delete the original sample produced so that it will not need confirmation to overwrite the data when the next original sample will be drawn
    Range("B2:B51").Select
    Selection.ClearContents

Next n

Application.ScreenUpdating = True

Sheets("Coverage Results").Activate
Range("I2").Select

End Sub

This isn't exactly an answer to your question, but I have had occasion to do simulations that required simulating Poisson random variables and have written my own user-defined function for it. 这并不完全是您问题的答案,但是我有机会进行一些需要模拟Poisson随机变量的模拟,并为此编写了自己的用户定义函数。 It works by simulating a Poisson process and counting the number of arrivals within 1 unit of time. 它通过模拟泊松过程并计算1个单位时间内的到达次数来工作。 Remove the comment flag from Application.Volatile if you want it to behave like the worksheet function Rand() and recalculate whenever anything changes on the spreadsheet. 如果希望它的工作方式类似于工作表函数Rand() ,请从Application.Volatile删除注释标记,并在电子表格上发生任何更改时重新计算。

Function RandPoisson(lambda As Double) As Long
    'Application.Volatile
    Dim count As Long
    Dim x As Double, sum As Double
    Do While True
        x = -Log(Rnd()) / lambda
        If sum + x > 1 Then
            RandPoisson = count
            Exit Function
        Else
            sum = sum + x
            count = count + 1
        End If
    Loop
End Function

To test this, I wrote the following sub and compared the output with the built-in function Poisson.Dist : 为了测试这一点,我编写了以下子代码,并将输出与内置函数Poisson.Dist

Sub test()
    Dim i As Long, p As Long
    Dim counts As Variant

    ReDim counts(0 To 9)
    Randomize
    For i = 1 To 1000000
        p = RandPoisson(3)
        If p < 10 Then counts(p) = counts(p) + 1
    Next i
    For i = 0 To 9
        Range("B2").Offset(i).Value = counts(i) / 1000000
    Next i
End Sub

Output: 输出:

在此处输入图片说明

Even though it involves a million simulations, it only takes about 1 second to compute. 即使涉及一百万次模拟,计算也只需要大约1秒钟。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM