Announcement

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

  • Program Graph: Allowing for Varying Number of Variables

    Dear Statalisters,

    I would like to write a program that automatically plots the means of variables over time for different groups of variables.
    Taking a toy data example, let - x_1, x_2 - and - x_3, x_4, x_5 - form variable groups, respectively.

    Below is a simplified version of my current program. It works fine if I specify exactly four variables but any number of variables below that makes Stata throw the error "too few variables specified". When specifying any number of variables greater than four, the program stops after plotting the first four variables. So far, I have tried "capture noisily" (see below) but without success.

    Any help (also of course on how to write a neater program in general) is appreciated. Thank you very much.

    Code:
    // Toy data
        clear
        set seed 8881
    
        set obs 80
        egen year = seq(), from(2016) to (2019) block(1)
        forvalues i = 1/5 {
            gen x_`i'          = 1 + `i' + runiformint(1, 5) if year == 2016
            replace x_`i'    = 2 + `i' + runiformint(1, 5) if year == 2017
            replace x_`i'    = 3 + `i' + runiformint(1, 5) if year == 2018
            replace x_`i'    = 4 + `i' + runiformint(1, 5) if year == 2019
            
            label variable x_`i' "Label for variable `i'"
        }
    
    // Program
        cap program drop plotmean
        program define plotmean
        syntax varlist
      
            local count: word count `varlist'
            forvalues i = 1/`count' {
                local x_`i': word `i' of `varlist'
              
                local lab_`i': var label `x_`i''
                
                tempvar x_`i'_mean
                egen `x_`i'_mean' = mean(`x_`i''), by(year)
            }
          
            capture noisily {
            twoway     ///
                     connected `x_1_mean' year, sort ///
                ||    connected `x_2_mean' year, sort ///
                ||    connected `x_3_mean' year, sort ///
                ||    connected `x_4_mean' year, sort ///
                legend(order(1 "`lab_1'" 2 "`lab_2'"       ///
                                     3 "`lab_3'" 4 "`lab_4'" ))
            }
            
        end

  • #2
    The basic issue is that your program explicitly plots each line assuming there are four variables instead of relying on the user input to tell you how many variables there are. One way to fix it:

    Code:
    // Toy data
    clear
    set seed 8881
    set obs 8
    gen year = _n+2000
    expand 10
    forvalues i = 1/5 {
        gen var`i'          = year/runiformint(1,100)
        label variable var`i' "Label for variable `i'"
    }
    
    // Program
    
    cap program drop plotmean
    program define plotmean
        syntax varlist(numeric)
        forvalues i = 1/`:word count `varlist'' {
            local x_`i': word `i' of `varlist'
            local lab_`i': var label `x_`i''
            tempvar x_`i'_mean
            egen `x_`i'_mean' = mean(`x_`i''), by(year)
            local command `command' connected `x_`i'_mean' year,sort ||
            local legend `legend' `i' "`lab_`i''"
        }
        twoway `command',legend(order(`legend'))
    end
    Last edited by Ali Atia; 08 Mar 2021, 06:33.

    Comment


    • #3
      Here are some ideas.


      Code:
      program myplotmean  
          syntax varlist(numeric) , [ * ]
          preserve
          local nvars : word count `varlist'
          tokenize `varlist'
          local x ``nvars''
          local varlist : list varlist - x
      
          local j = 0
          foreach v of local varlist {
              local ++j
              local label`j' : var label `v'
              if `"`label`j'''"' == "" local label`j' "`v'"
          }
          
          collapse `varlist', by(`x')
          
          local j = 0
          foreach v of local varlist {
              local ++j
              label var `v' "`label`j''"
          }
          
          line `varlist' `x', `options'
      end
      Code:
      myplotmean x* year
      Last edited by Nick Cox; 08 Mar 2021, 07:12.

      Comment


      • #4
        That's awesome, exactly what I was looking for. Thank you very much to both of you!

        Comment

        Working...
        X