Announcement

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

  • Errors using input command inside program

    Dear Statalist,

    I am trying to save the results of a short program I have written in a separate data set. For that I want the program to create a new data set and store several numbers (and strings). I thought this might be easily doable using the input command. However I am getting and error that I don't understand (see code examples below). Does someone have an idea what's going wrong here? Is there a different approach to my problem?

    Code:
    version 12
    clear
    
    capture program drop test
    program define test    
        if 1 { 
            input number
                3
            end
        }    
    end
    Produces the error:
    unrecognized command: } invalid command name

    And with:
    Code:
    capture program drop test
    program define test    
        input number
            3
        end
    end
    I get the error:
    unrecognized command: end

    What's going on there?


  • #2
    Not going to work given the ambiguity of end

    The first end is taken to mean the end of the program you're defining. Given that a following brace makes no sense to Stata, or alternatively the second end makes no sense, as it can't be the start of anything.

    If the program is to create new data, then include in your program something like


    Code:
    clear 
    set obs 1 
    gen number = 3
    or (better style in my view) put that sort of thing in a do-file you run first.



    Comment


    • #3
      That explanation makes perfect sense. Thank you!

      Unfortunately, your work around isn't feasible in my case (at least I don't see how): The program I'm working on uses regression results and some additional parameters as input and calculates several statistics on that basis. The idea was to run the program several times with (the same regression results but) different additional parameters as input and report the calculated statistics along with the parameters used in a separate data set (in order to export that table to excel for documentation/presentation purposes).

      I suspect that this approach doesn't make the best use of facilities of the Stata language. I would be happy about a hint on how something like this can best be approached the Stata way!

      (Sorry for going off topic a bit. I hope there is still enough of a connection to justify answering in this post.)

      Comment


      • #4
        I don't think you're being obscure at all, but sorry I don't understand precisely what you want instead. But why do you think you need variables? How about locals, scalars, matrices, Mata?

        Comment


        • #5
          What I want to achieve is very similar to the following:

          1. Running a logistic regression
          2. Running several -estat class- calls with a range of different cutoff values
          (3. Documenting the results of each call in a separate table)
          4. Plotting the share of "Correctly classified" by the cutoff value

          In this comparison estat class is like the program I am trying to write. I want to keep it's results before running it a second time so that I can use them (in a plot) later. Ideally all of that would run as automatic as possible.

          I thought about the following approaches:
          -eclass: I thought about making my program an eclass program and storing it's estimates with -estimates store-. But that would mean that my program overwrites the regression results. Also I would have to get the results into a data set before plotting them which would mean doing a lot by hand (outside of a program definition) or being back to the original problem.
          -rclass: I could define my program as rclass (like estat class). But then I would overwrite the results with each new call of my program. (Plus the plotting part would be as messy as with eclass.)
          -matrix: I could store my results in a predefined matrix, adding a new row for each call of my program. After that I could store the matrix as a data set and do the plotting. The downside with this is, that for step 3.) I would ideally also have string variables in my documentation table, which I think is not possible with matrices (?). Additionally this solution still seems a bit messy to me (predefining the matrix, passing it to the program, turning it into a dataset after the whole process).

          So is the matrix approach a good way to do this?






          Comment


          • #6
            I am not going to be much extra help, but the whole idea of writing a program (strict sense) here seems moot to me. This sounds to me like a do-file task where you just take commands' results and assemble them all. Sometimes when you work with a do-file repeatedly you start seeing a way to rewrite it as a program. Conversely, there's not a lot of point to writing a program and wiring into it lots of very specific choices.

            Conversely, you're fully aware that a r-class program or a e-class program would just stomp on results you want lying around, so on those grounds too a program is perhaps better avoided.

            You're caught here possibly in that posting a lot of code is likely to be met with silence, but your question isn't easily answered, so far as I can see.

            Comment


            • #7
              In case someone is having a similar/related problem and is interested in what I chose for a solution, here's some code.

              Code:
              program define someprogram
                  args filename
              
                  * some calculations
              
                  preserve
                  clear
              
                  quietly {
                      capture confirm file "`filename'.dta"
                      if _rc != 0 { 
                          set obs 1
                          gen somevalue = `thatvalue'
                      }
                      else {
                          use "`filename'.dta"
                          set obs `=_N+1'
                          replace somevalue = `thatvalue' if _n == _N
                      }
                  }
              
                  save `filename'.dta, replace
              
              end
              Thanks to Nick, who actually gave me all the answers I needed already in his first response (#2)! I just didn't realize it...

              Comment


              • #8
                Max,

                I am not sure, but I guess you are trying to re-invent the postfile/post/postclose commands.

                For efficiency reasons it is a good idea to avoid preserve/use/save commands in the iterative approach you have. Simply writing a line to a text file should be sufficient.

                I hope thatvalue local is defined somewhere in the "some calculations" part, since it is not obviously present in the code you've posted.

                Best, Sergiy

                Comment


                • #9
                  Sergiy,

                  You are right, I didn't know about the post* commands. They are very close to what I want. The only issue I have with them is that (as far as I can see) every time -postfile- is called a new data set will be created (or an existing one overwritten). I can't really use it to add to an existing one, right?

                  I admit that this should rarely be a problem. But imagine my program runs an analysis (which might take a while, maybe even overnight) and afterwards I look at the results maybe change some parameters (or even some of the code) and run an additional analysis - which means I wouldn't be able to get all the results in one go. If I want the results to end up in one data set with using -postfile- I would need to store them separately first and then append them afterwards. With my code (although admittedly probably not very efficient) I can just keep adding to a data set. Or am I wrong about this?

                  Comment

                  Working...
                  X