Announcement

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

  • Variable already exists error after clearing within a programme

    Hi Statalisters,

    I've put together a programme to assign members of my organization to QA documents (i know, i work in esteemed company). It's returning the error that the variable id already exists though, even though at the beginning of the programme it clears existing data.

    Code:
    *! version 1.1  10 Feb 2017  Chris Larkin
    
    capture program drop whoforqa
    program whoforqa
    syntax [, SEED(int)]
    
    qui{
    
    preserve
    forvalues i = 1/15{
    noisily di " "
    }
    
    clear
    input str18 firstname str18 lastname
    "Jeff" "Bridges"
    "Leonardo" "Di Caprio"
    "Jack" "Nicholson"
    "Samuel" "Jackson"
    "Orlando" "Bloom"
    "Johnny" "Depp"
    "Nicolas" "Cage"
    "Robert" "De Niro"
    "Chris" "Larkin"
    end
    
    sort firstname lastname
    gen id = _n
    set seed `seed'
    gen rand = runiform()
    egen rank = rank(rand)
    
    noisily: di in red "And the person doing the QA is...."
    noisily: li firstname lastname if rank==_N, noheader clean noobs
    
    forvalues i = 1/15{
    noisily di " "
    }
    restore
    }
    I haven't saved it in my personal folder yet, but I should be able to just run it as a do-file and run it thusly

    Code:
    sysuse auto, clear
    whoforqa

    Any ideas what's going wrong?
    Last edited by Chris Larkin; 10 Feb 2017, 16:50.

  • #2
    So it was the end, after the input command that leads to the issue. Where i'm just trying to close the input command, i'm actually closing the program. This poses another problem though - is it even possible to use input within a program, given that it requires end?


    Comment


    • #3
      Ok so i've removed the input command from the programme, but am still getting an invalid syntax error when trying to call the program from a separate do-file. If anyone can offer pointers here that'd be appreciated!

      The programme
      Code:
      *! version 1.1  10 Feb 2017  Chris Larkin
      
      capture program drop whoforqa
      program whoforqa
      syntax [, * SEed(int)]
      version 13
      
      qui{
      
      preserve
      forvalues i = 1/15{
      noisily di " "
      }
      
      clear
      set obs 10 
      gen firstname = "Jeff" in 1
      replace lastname = "Leonardo" in 2
      replace lastname = "Jack" in 3
      replace lastname = "Samuel" in 4 
      replace lastname = "Orlando" in 5
      replace lastname = "Johnny" in 6
      replace lastname = "Nicolas" in 7
      replace lastname = "Robert" in 8 
      replace lastname = "Chris" in 9
      
      gen lastname = "Bridges" in 1
      replace lastname = "Di Caprio" in 2
      replace lastname = "Nicholson" in 3
      replace lastname = "Jackson" in 4 
      replace lastname = "Bloom" in 5
      replace lastname = "Depp" in 6
      replace lastname = "Cage" in 7
      replace lastname = "De Niro" in 8 
      replace lastname = "Larkin" in 9
       
      sort firstname lastname
      gen id = _n
      set seed `seed'
      gen rand = runiform()
      egen rank = rank(rand)
      
      noisily: di in red "And the person doing the QA is...."
      noisily: li firstname lastname if rank==_N, noheader clean noobs
      
      forvalues i = 1/15{
      noisily di " "
      }
      restore
      }
      end
      Trying to call it:
      Code:
      sysuse auto, clear
      whoforqa

      Comment


      • #4
        TL;DR: Here's the fix
        Code:
        syntax [, * SEed(int 42)]
        Using set trace on shows us that your program fails at the syntax command, which investigation shows does not follow the required syntax for syntax. (Is this meta enough for all of us? )

        Because your seed option is an optional option rather than a required option, and accepts an integer, omitting the default value for the option is not an option. (Gah! I'm drowning in meta.)

        Once you fix the syntax of your syntax, you'll also want to change "lastname" to "firstname" in the nine lines beginning with the one containing "Leonardo".

        Comment


        • #5
          Haha well to comment on your comment of my comment's comment, thanks for this! It's up and working fine now. I appreciate the programme is a little ridiculous, but it seemed like the fairest way to assign QA internally. Can I ask what the 42 does?

          Comment


          • #6
            What 42 does? For that we go here in Wikipedia.

            Oh, you mean what it does in your syntax statement? It's the value assigned to the local macro seed within your program if you neglect to specify the seed option on invoking the program.

            Comment


            • #7
              Great! I might see if I can make it a bit longer. There's not a huge list of names, but I feel the seed should be a tad longer. Many thanks!

              Comment


              • #8
                Chris, you very much need to read the output of help set seed. The value of the seed, and its use in the generation of random numbers, bears no relationship to the quantity of random numbers you will be generating.

                With that said, you need to understand that if you set the seed to the same number within your program, then every time you run the program the same sequence of "random" numbers will be generated, and in your case, the same person will be chosen for QA.
                Code:
                capture program drop whoforqa
                program whoforqa
                syntax [, SEed(int 42)]
                version 13
                
                preserve
                clear
                quietly {
                set obs 9
                gen firstname = "Jeff" in 1
                replace firstname = "Leonardo" in 2
                replace firstname = "Jack" in 3
                replace firstname = "Samuel" in 4
                replace firstname = "Orlando" in 5
                replace firstname = "Johnny" in 6
                replace firstname = "Nicolas" in 7
                replace firstname = "Robert" in 8
                replace firstname = "Chris" in 9
                gen lastname = "Bridges" in 1
                replace lastname = "Di Caprio" in 2
                replace lastname = "Nicholson" in 3
                replace lastname = "Jackson" in 4
                replace lastname = "Bloom" in 5
                replace lastname = "Depp" in 6
                replace lastname = "Cage" in 7
                replace lastname = "De Niro" in 8
                replace lastname = "Larkin" in 9
                 
                sort firstname lastname
                if `seed'>=0 set seed `seed'
                gen rand = runiform()
                sort rand
                }
                
                display in red "And the person doing the QA is `=firstname[_N]' `=lastname[_N]'"
                
                restore
                end
                Code:
                . whoforqa
                And the person doing the QA is Leonardo Di Caprio
                
                . whoforqa
                And the person doing the QA is Leonardo Di Caprio
                
                . whoforqa
                And the person doing the QA is Leonardo Di Caprio
                
                .
                It gets even more subtle. If you were to exit Stata, launch Stata, immediately run the do-file creates the program, immediately run the program without setting the seed (whoforqa, seed(-1) in my program above will cause the seed to not be set), and exit Stata, you will get the same person chose for QA each time. This a a result of the fact that each time Stata is launched, it sets the seed to a fixed value. Again, all this follows from the documentation in help set seed.

                So if you are creating a program that will be run every so often to make a random choice among QA candidates, you are going to have to do something ensure that it doesn't use the same seed each time it is run.
                Last edited by William Lisowski; 11 Feb 2017, 13:32.

                Comment


                • #9
                  Hi William,

                  Thanks for spelling this out. I've read through the set seed help file, and have reached a somewhat counter-instructed conclusion. Although the help file says not to use one of Stata's inbuilt pseudo-random number generator functions to generate the seed, the reason it gives is because this will eventually converge on a pattern. While obviously true, the purpose of the practical use of this programme means that it will, as you say, only be run once every now and then to randomly draw one name from a hat. It is not running through simulations or using a random number to impute missing values (two examples the help file outlines as a caution against using pseudo-random numbers as the seed).

                  As such, something like this seems perfectly sensible:

                  Code:
                  syntax [, * SEed(int `=round(runiform(1,10000000),1)')]
                  Considering the programme will be run at a maximum a few hundred times a year, and would require many more calls before it converges

                  Comment


                  • #10
                    Again, if Stata is launched, the do-file that defines whoforqa immediately run, and then the whoforqua command run, the same number will always be drawn by the runiform that sets the seed, so the same seed will always be used, and thus the same name chosen.

                    I'd be more likely to try
                    Code:
                    syntax [ , * SEed( int `= clock( c(current_time), "hms" )' ) ]
                    With the caveat that given what you've shown us of your code, I do not understand the inclusion of the asterisk in the list of options.

                    Comment

                    Working...
                    X