Announcement

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

  • How to generate a local containing a list of varlists from other locals

    Dear Statalisters,

    I want to create a local containing sets of explanatory variables which are themselves stored as locals. The local is intended as an input to a program. Doing this manually works. However, I would like to automize this.

    My strategy is to create the local via a loop and adding each set of explanatory variables in turn (controls_1 - controls_3). What I want to end up with is a "string of strings". However, I have trouble with how to deal with the compound double quotes necessary for that.

    Below I post a MWE. My main problem is the foreach loop populating `whatIget'. Does any of you have a hint on the correct use of compound double quotes to make `whatIget' equivalent to `whatIwant'?

    Any help is much appreciated!
    Ben

    Code:
    ** minimum working example
    
    ssc install estout
    
    // gen fake data
    clear
    set obs 100
    gen depvar = runiform(0,1)
    gen x1 = runiform(0,1)
    gen x2 = runiform(0,1)
    gen x3 = runiform(0,1)
    
    // sets of explanatory variables
    local controls_1 `"x1"'
    local controls_2 `"x2"'
    local controls_3 `"x1 x2 x3"'
    
    // local selecting the sets of explanatory variables I want to pass to the function
    local controlset 1 2 3
    
    // manually, this works
    local whatIwant `"`"x1"' `"x2"' `"x1 x2 x3"'"'
    di `whatIwant'
    
    // trying to automize whatIwant: 
    local whatIget
    foreach set in `controlset' {
    di "`controls_`set''"
    local whatIget `whatIget' `controls_`set''
    }
    di "`whatIget'"
    
    ** testing the two versions (final use intended is to pass this to a program, example below just for clarification of the problem)
    
    // testing whatIwant
    foreach model in `whatIwant' {
    quietly: eststo: reg depvar `model'
    }
    
    esttab // want: 3 models, get: 3 models
    eststo clear
    
    // testing whatIget
    foreach model in `whatIget' {
    quietly: eststo: reg depvar `model'
    }
    
    esttab // want: 3 models, get: 5 models
    eststo clear


  • #2
    I'm confused, why do you need the compound quotes? E.g. you can define

    Code:
    local controls_1 "x1"
    And it will store the string "x1", no need for the compound quotes. If you then want to add controls1-3 together, you can simply
    Code:
    local whatIGet "`controls_1' `controls_2' `controls_3'"
    If you want to regress with the different control options, you can loop over the number
    Code:
    forvalues i = 1/3 {
     reg depvar `controls_`i''
    }

    Comment


    • #3
      Hi Jesse, many thanks for your reply!

      My idea is that I want to use the local `controlset' to quickly change the different sets of controls in `whatIget' rather than pasting manually which controls I want in `whatIget' everytime as in your example above.

      The precise problem is that in the way you define `whatIget', x1-x3 in `controls_3' are treated as individual list members rather than a single string. (see code below reproducing this)

      My question therefore is: how do I have to enclose this in quotes to get ""x1" "x2" "x1 x2 x3"" (3 string items) rather than "x1 x2 x1 x2 x3" (5 items)?

      Thanks again!
      Ben

      Code:
      clear
      set obs 100
      gen depvar = runiform(0,1)
      gen x1 = runiform(0,1)
      gen x2 = runiform(0,1)
      gen x3 = runiform(0,1)
      
      
      local controls_1 `"x1"'
      local controls_2 `"x2"'
      local controls_3 `"x1 x2 x3"'
      
      
      local whatIget "`controls_1' `controls_2' `controls_3'"
      
      foreach control in `whatIget' {
      reg depvar `control'
      }
      // This runs 5 regressions instead of the 3 regressions I intend it to run.

      Comment


      • #4
        To be honest, I really wouldn't suggest doing it that way. It is a lot easier and safer to just generate separate locals or generate the control set on the go. Creating lists within locals is tricky, hard to read code and error-prone. If you really want to generate all the sets in one local, then I suggest using a different separator between variables within a local, e.g. x1 x1!x2 x1!x2!x3 and then using the subinstr() function to remove the separator on the go.

        Code:
        local sets "x1 x1!x2 x1!x2!x3"
        foreach set of local sets {
        local set = subinstr("`set'", "!", " ", .)
        reg depvar `set'

        Comment


        • #5
          I appreciate your reservations. Thanks nonetheless for your suggestion!

          Comment


          • #6
            You can store substrings delimited by double-quotes in local macros. You can then loop over each as follows:
            Code:
            local controls x1 "x1 x2" "x1 x2 x3" x4
            foreach control of local controls {
                dis "reg depvar `control'"
            }
            and the results:
            Code:
            . foreach control of local controls {
              2.         dis "reg depvar `control'"
              3. }
            reg depvar x1
            reg depvar x1 x2
            reg depvar x1 x2 x3
            reg depvar x4

            Comment

            Working...
            X