Announcement

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

  • Error in program code

    Hello,

    I would like to write a program that creates a random dataset.
    My codes are as follows.

    ********************************************
    capture program drop testt
    program testt, rclass
    version 18.0
    syntax, n(integer) expand(integer)

    // GENERATE THE RANDOM DATA
    clear
    set obs `n'
    gen id=_n
    gen bn=uniform()<0.3
    gen bb=uniform()<0.2
    gen ab=uniform()<0.4
    gen spec = ceil(runiform(0, 5))

    forvalues i = 1(1)18 {
    generate case`i' = 1
    }
    reshape long case, i(id) j(case_no)
    gen idd=_n
    save "test.dta", replace
    clear

    input transfer cog_chara urination route_d medication agep
    1 1 1 0 1 0
    0 0 1 1 1 1
    1 1 1 1 1 1
    1 1 0 1 1 0
    1 0 0 1 1 1
    1 0 1 1 1 0
    1 1 1 0 0 1
    1 1 1 1 1 1
    0 1 1 0 1 1
    1 1 1 1 0 0
    1 0 1 0 1 1
    1 0 1 1 0 1
    0 1 0 1 1 1
    0 1 1 1 0 1
    1 1 0 1 0 1
    1 1 0 0 1 1
    0 0 0 0 0 0
    0 1 1 1 1 0
    end
    expand `expand'

    egen id = seq(), b(18)
    gen idd=_n
    save "test1.dta", replace
    clear

    use "test.dta"
    merge 1:1 idd using "test1.dta"
    end

    testt, n(100) expand(100)

    ************************************

    But, the program fails by issueing the following error message.

    . expand `expand'
    =exp required

    Could anyone please help me how to solve this problem?

    Thanks in advance.

  • #2
    I think that you cannot enter a dataset using input within a Stata program, because you must use end and that signals also to program [define] the end of the program, too. When that happens, your expand `expand' line of code no longer has a definition of the local macro—it's now outside of the program definition.

    So, if you're going to use input for your invariant dataset, then you'll need to park it somewhere outside of the program definition. Below I show one possibility just for illustration, which is to store the invariant dataset in a (temporary) dataset file and reference its location with a program argument (option). There are other approaches, of course, and it doesn't need to be a temporary dataset file.
    Code:
    version 18.0
    
    clear *
    
    input byte(transfer cog_chara urination route_d medication agep)
    1 1 1 0 1 0
    0 0 1 1 1 1
    1 1 1 1 1 1
    1 1 0 1 1 0
    1 0 0 1 1 1
    1 0 1 1 1 0
    1 1 1 0 0 1
    1 1 1 1 1 1
    0 1 1 0 1 1
    1 1 1 1 0 0
    1 0 1 0 1 1
    1 0 1 1 0 1
    0 1 0 1 1 1
    0 1 1 1 0 1
    1 1 0 1 0 1
    1 1 0 0 1 1
    0 0 0 0 0 0
    0 1 1 1 1 0
    end
    tempfile reference
    quietly save `reference'
    
    program define testt, // rclass
        version 18.0
        syntax, n(integer) Expand(integer) Reference(string)
    
        drop _all
        quietly set obs `n'
    
        generate int id = _n
        generate byte bn = uniform() < 0.3
        generate byte bb = uniform() < 0.2
        generate byte ab = uniform() < 0.4
        generate byte spec = ceil(runiform(0, 5))
    
        forvalues i = 1/18 {
            generate byte case`i' = 1
        }
        quietly reshape long case, i(id) j(case_no)
        generate int idd = _n
    
        tempfile test
        quietly save `test'
    
        drop _all
        quietly use `reference'
    
        quietly expand `expand'
    
        egen int id = seq(), block(18)
        recast int id
        generate int idd = _n
        
        merge 1:1 idd using `test', assert(match) nogenerate noreport
    end
    
    testt, n(2) expand(2) reference(`reference')
    list, noobs sepby(id) abbreviate(20)
    
    exit
    Notes:

    1. egen . . . seq() seems to have a bug inasmuch as it ignores the storage type int and so I had to manually recast the generated variable to int in order to avoid a message from merge about promoting its storage type to match that of the using dataset.

    2. Your program doesn't need the rclass designation and so I commented that out.

    3. I didn't try to refactor your code (make any substantive changes) otherwise.

    I'm curious as to what this is for.

    Comment


    • #3
      Are you running the program all at once or line by line? The latter could explain why the local macro expand is not visible to the code.

      EDIT Joseph Coveney has a much better explanation in #2. (I started writing this some time ago, which is why his answer was not visible to me until I had posted mine.)

      Otherwise my main reaction is that a program that wires in very specific details is neither needed nor particularly helpful. I would recast this as a do-file.

      Edited to a file miyuki.do the file below works with a call

      Code:
      do miyuki 100 100
      I used runiform() not uniform() for consistency and changed one call to use runiformint()

      You might also consider setting the seed for random numbers.


      Code:
      args n expand
      
      // GENERATE THE RANDOM DATA
      clear
      set obs `n'
      gen id=_n
      gen bn = runiform()<0.3
      gen bb = runiform()<0.2
      gen ab = runiform()<0.4
      gen spec = runiformint(1, 5)
      
      forvalues i = 1(1)18 {
      generate case`i' = 1
      }
      reshape long case, i(id) j(case_no)
      gen idd=_n
      save "test.dta", replace
      clear
      
      input transfer cog_chara urination route_d medication agep
      1 1 1 0 1 0
      0 0 1 1 1 1
      1 1 1 1 1 1
      1 1 0 1 1 0
      1 0 0 1 1 1
      1 0 1 1 1 0
      1 1 1 0 0 1
      1 1 1 1 1 1
      0 1 1 0 1 1
      1 1 1 1 0 0
      1 0 1 0 1 1
      1 0 1 1 0 1
      0 1 0 1 1 1
      0 1 1 1 0 1
      1 1 0 1 0 1
      1 1 0 0 1 1
      0 0 0 0 0 0
      0 1 1 1 1 0
      end
      expand `expand'
      
      egen id = seq(), b(18)
      gen idd=_n
      save "test1.dta", replace
      clear
      
      use "test.dta"
      merge 1:1 idd using "test1.dta"

      Last edited by Nick Cox; 10 Oct 2024, 07:01.

      Comment

      Working...
      X