Announcement

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

  • Repeating iterations with different desired obs

    I want to perform 1,000 iterations, where each iteration generates 30 random coin flips, counts the heads, and stores the result in a single dataset with 1,000 rows (one for each iteration).

    currently I have this code:

    HTML Code:
    clear all
    local n 30
    local reps 1000
    set obs `reps'
    gen headcount = .
    
    forvalues i =1/`reps' {
    set obs = `n'
    gen u = runiform(0,1) // random value between 0 and 1
    gen heads = u > 0.5 // categorical data, 1 if heads, 0 if tails //
    count if heads==1
    replace headcount = r(N) in `i'
    drop heads
    drop u
    }
    if you delete the line with set obs = `n' it works but only insofar as it will be able to close the loop. The number of "coin flips" for each sample will be equal to 'reps'.


    the code within the loop,

    Code:
    set obs 30 // 30 coin flips //
    gen u = runiform(0,1) // random value between 0 and 1
    gen heads = u > 0.5 // categorical data, 1 if heads, 0 if tails //
    summarize heads
    count if heads==1
    works like a charm for one iteration. So how can I embed the latter into the former?

    also this is my first post. please advise if I'm posting code incorrectly.

    Thanks!
    Last edited by Sam Lawrence; 18 Jan 2025, 01:10.

  • #2
    Sam:
    welcome to this forum.
    You may want to try somethng along the following lines:
    Code:
    . set obs 1000
    Number of observations (_N) was 0, now 1,000.
    
    . 
    . gen counter=.
    (1,000 missing values generated)
    
    . 
    . quietly forvalues i =1/1000 {
    . 
    . g lambda=.
    . 
    . gen u = runiform(0,1) in 1/30
    . 
    . gen heads = u > 0.5
    . 
    . sum heads, meanonly
    . 
    . replace lambda=r(mean) 
    . 
    . replace counter=lambda in `i'
    . 
    . drop heads
    . 
    . drop u
    . 
    . drop lambda
    . 
    . }
    
    . sum counter
    
        Variable |        Obs        Mean    Std. dev.       Min        Max
    -------------+---------------------------------------------------------
         counter |      1,000     .985073    .0028255       .978       .994
    
    .
    Kind regards,
    Carlo
    (StataNow 18.5)

    Comment


    • #3
      I ended up using

      Code:
      gen u = runiform(0,1) in 1/`n'
      the only problem was that empty observations end up as 1 in the "heads" variable with the code

      Code:
      gen heads = u>0.5
      but you can get around this by realizing that it will simply add to the

      Code:
      countif heads == 1
      count by the difference between `reps' and `n'

      so I just made the "replace" code

      Code:
      replace hc = r(N)-(`reps'-`n') in `i'

      so now the full code is:

      Code:
      clear all
      local n 30 
      local reps 50
      set obs `reps'
      gen hc = .
      
      forvalues i =1/`reps' {
          quietly{
              gen u = runiform(0,1) in 1/`n' // random value between 0 and 1 in 1 through `n' count //
              gen heads = u > 0.5 // categorical data, 1 if heads, 0 if tails //
              count if heads==1
              replace hc = r(N)-(`reps'-`n') in `i'
              drop heads
              drop u
      }
      }
      Last edited by Sam Lawrence; 18 Jan 2025, 12:48. Reason: add full code

      Comment


      • #4
        There are several ways to do this. One is to use frames. Another of some vintage is to call up postfile.

        The most notable point about #3 is that it's good practice to set seed and make that explicit.


        Code:
        * I want to perform 1,000 iterations, where each iteration generates 30 random
        * coin flips, counts the heads, and stores the result in a single dataset with 1,000 rows (one for each iteration).
        
        clear
        set obs 30
        set seed 314159
        
        gen heads = .
        
        postfile whatever fraction using results, replace
        
        forval i = 1/1000 {
            replace heads = runiform() > 0.5
            su heads, meanonly
            post whatever (r(mean))
        }
        
        postclose whatever
        
        use results, clear
        
        summarize fraction
        I didn't literally count the heads, but you could do that instead if it really is what is wanted:

        [CODE]
        forval i = 1/1000 {
        count if runiform() > 0.5
        post whatever (r(N))
        }
        [CODE]
        The variable concerned is better called heads, or whatever else you want.
        Last edited by Nick Cox; 19 Jan 2025, 05:50.

        Comment


        • #5
          Here for comparison is @Carlo Lazzaro's code, tweaked so that the similarities and differences are clearer.

          Code:
          clear 
          set obs 1000
          set seed 314159 
          
          gen counter = . 
          
          gen u = . 
          
          quietly forvalues i = 1/1000 {
          
          replace u = runiform(0,1) in 1/30
          count if u > 0.5 in 1/30 
          
          replace counter = r(N) in `i'
          
          }

          Comment

          Working...
          X