Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • returning values from .ado program

    Hi, all. I'm writing an ado script to generate probabilities from a beta distribution using the mean and standard deviation of the distribution rather than the alpha and beta values. The program calculates the results I'm looking for. However, I'm wrestling with returning results.

    Ideally I'd be able to do something like:
    Code:
    gen myNewVar=betaParams .5 .2.
    However, when I do this, I get: betaParams not found, r(111)

    Any thoughts? Here's the code.

    Code:
    cap  program drop betaParams
    program betaParams
        version 14
    
        args  mean sd
    
        local constant=(`mean'*(1-`mean')/(`sd'^2))-1
        
        local a=`mean'*`constant'
        local b=(1-`mean')*`constant'
    
        if (`a' <.05 | `b' <.15) {
            di as error "invalid parameters"
            exit 110
        }
        di rbeta(`a', `b')  
        
    end



    Last edited by Geoff Dougherty; 25 Aug 2015, 09:51.

  • #2
    That desired syntax is a long way from anything Stataish.

    As it stands, the program will produce just a single scalar which is a random draw from a specified beta distribution.

    You can take this in two directions, adding a generate() option to the program to extended that to an entire variable, or saving the two constants calculated.

    The second is a little easier and more general:

    Code:
     
    program betaParams, rclass  
        version 14
        args mean sd 
        tempname constant     
        scalar `constant' =(`mean' * (1-`mean')/(`sd'^2))-1
        
        if (`mean' * `constant' < .05) | ((1 - `mean') * `constant') < .15) { 
            di as error "invalid parameters"
            exit 110
        }
    
        return scalar a = `mean' * `constant' 
        return scalar b = (1 - `mean') * `constant' 
    end
    I have not tested this program, or checked the statistical logic, but it works you can use its results r(a) r(b) in a call to rbeta()

    I've found that reading the chapters in [U] all the way through is actually the quickest way to get programming like this done.

    Comment


    • #3
      Nick,

      Thanks for the comments. After looking at them, I think this is probably best implemented as an egen program (as the intent is to pull a new value from the beta distribution for each record). After looking at the help files, though, I'm not seeing how to structure the syntax statement.

      For example,
      Code:
      syntax newvarname=/exp
      leaves me with exp that consists of a big blob of numbers with no delimiter if I issue -egen newvar=betaParams(.4 .2)-

      On the other hand, I can't sort out a way to provide named arguments as options without a preceding varlist or other main expression. For example: -egen newvar=betaParams, mean(.4) sd(.2)- yields an undefined function error with the syntax line as so:
      Code:
      syntax newvarname=/, mean(real 25) sd(real 5)
      Last edited by Geoff Dougherty; 25 Aug 2015, 14:26.

      Comment


      • #4
        That's not what I would advise. But

        1. if you want to write an egen function, model your syntax on existing egen functions

        2. there are precedents of egen functions that take no varlists.

        Code:
        viewsource _gseq.ado

        Comment


        • #5
          Thanks, Nick. _gseq was right on the money.

          For posterity, this seems to work:
          Code:
          * generates variable containing draws from beta distribution given mean and sd of distro
          
          cap  program drop _grbeta1
          program _grbeta1 
          version 14
              gettoken type 0 : 0
              gettoken g 0 : 0
              gettoken eqs 0 : 0
              gettoken lparen 0 : 0, parse("(")
              gettoken rparen 0 : 0, parse(")")
           
              syntax [if] [in] [ ,  Avg(real 5) Sd(real 5)]
          
              local constant=(`avg'*(1-`avg')/(`sd'^2))-1
              
              local a=`avg'*`constant'
              local b=(1-`avg')*`constant'
              
              if (`a' <.05 | `b' <.15) {
                  di as error "invalid parameters"
                  exit 110
              }
               
              gen `type' `g' = rbeta(`a', `b')  
               
          end

          Comment

          Working...
          X