Announcement

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

  • Can I recall a macro in a macro

    Hi,

    I have to run a series of OLS regression models, each with the same dep. variable but different indep. variables.

    I wanted to automate the process as follow:

    1. define macros as "list1" "list2" ... (each composed as depvar indepvars)
    2. using foreach

    when I try to recall the lists in foreach, I have to recall macro AND inside the macro the i of foreach, as follow

    $list`i'

    that just doesn't work.
    I even tried with local macros but the software just can't get the `i' inside the macro.

    How can I automate the process?

    HTML Code:
    webuse auto
    global list1 price mpg rep78 trunk
    global list2 price mpg rep78 weight
    global list3 price mpg rep78 trunk weight
    
    foreach i of numlist 1/3 {
    regress $list`i'
    }

    Thank you,

    Omar

  • #2
    This may work (using local instead of global):

    Code:
    webuse auto
    local list1 price mpg rep78 trunk
    local list2 price mpg rep78 weight
    local list3 price mpg rep78 trunk weight
    
    foreach i of numlist 1/3 {
    regress `list`i''
    }

    Comment


    • #3
      I did some googling and found in an old post (@Nick Cox) that curly brackets work:

      Code:
      webuse auto, clear
      global list1 price mpg rep78 trunk
      global list2 price mpg rep78 weight
      global list3 price mpg rep78 trunk weight
      
      foreach i of numlist 1/3 {
      regress ${list`i'}
      }

      Comment


      • #4
        Code:
         foreach i of numlist 1/3
        could be just
        Code:
        forval i = 1/3
        For that matter, what is the appeal or advantage of a loop here over three plain and simple statements? That is, this


        Code:
         
         regress price mpg rep78 trunk


        and its two siblings?
        Last edited by Nick Cox; 19 Feb 2023, 11:20.

        Comment


        • #5
          This post is not relevant anymore! I made a mistake. Sorry


          Dear Stata Enthusiasts

          I have a dataset with 50 samples. I would like to run regression for each sample separately. Because I will run a lot of regressions I would like to store these regressors in local/global macro so that everytime I run a regression, I only need to call the macro. This is because I needl to provide clean and readable code for other researchers.

          Even though, I understand that the macro is not found after the restore command, I do not know how to proceed further. Any help is much appreciated. Thank you!

          Code:
          local predictors_all_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.mom_child_loss_categorical i.mom_cohort
          
          local predictors_married_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth c.pop_age c.pop_age#c.pop_age i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.pop_edattain2 i.pop_edattain3 i.pop_edattain4 i.mom_cohort i.mom_child_loss_categorical
          
          levelsof sample
          foreach sample in `r(levels)' {
              preserve
              keep if sample == `sample'
              regress mom_fertility i.FirstDaughter `predictors_all_moms' [pweight=mom_perwt]
              regress mom_fertility i.FirstDaughter `predictors_married_moms' [pweight=mom_perwt]
              restore
          }
          Code:
          * Example generated by -dataex-. For more info, type help dataex
          clear
          input long sample float FirstDaughter double mom_perwt int mom_age byte mom_edattain1
          50201101 . 20 35 0
          50201101 . 20 23 0
          50201101 . 20 20 0
          50201101 . 20 22 0
          50201101 . 20 22 0
          50201101 . 20 25 0
          50201101 . 20 25 0
          50201101 . 20 28 0
          50201101 . 20 28 0
          50201101 . 20 25 0
          50201101 1 20 30 0
          50201101 . 20 30 0
          50201101 0 20 28 0
          50201101 . 20 28 0
          50201101 . 20 27 0
          50201101 . 20 27 0
          50201101 . 20 24 0
          50201101 0 20 30 0
          50201101 . 20 30 0
          50201101 . 20 30 0
          50201101 . 20 23 0
          50201101 1 20 28 0
          50201101 . 20 28 0
          50201101 . 20 22 0
          50201101 . 20 22 0
          50201101 . 20 45 0
          50201101 1 20 27 0
          50201101 . 20 27 0
          50201101 0 20 28 0
          50201101 . 20 28 0
          50201101 . 20 26 0
          50201101 . 20 26 0
          50201101 0 20 35 0
          50201101 . 20 35 0
          50201101 . 20 35 0
          50201101 . 20 22 0
          50201101 . 20 22 0
          50201101 . 20 35 0
          50201101 . 20 22 0
          50201101 . 20 22 0
          50201101 . 20 22 0
          50201101 0 20 26 0
          50201101 . 20 26 0
          50201101 . 20 40 0
          50201101 . 20 20 0
          50201101 . 20 25 0
          50201101 . 20 25 0
          50201101 . 20 20 0
          50201101 0 20 30 0
          50201101 . 20 30 0
          50201101 . 20 30 0
          50201101 . 20 32 0
          50201101 . 20 32 0
          50201101 . 20 22 0
          50201101 . 20 26 0
          50201101 . 20 22 0
          50201101 . 20 25 0
          50201101 . 20 25 0
          50201101 0 20 30 0
          50201101 . 20 30 0
          50201101 . 20 24 0
          50201101 . 20 24 0
          50201101 . 20 30 0
          50201101 . 20 22 0
          50201101 . 20 25 0
          50201101 . 20 25 0
          50201101 1 20 30 0
          50201101 . 20 30 0
          50201101 . 20 30 0
          50201101 . 20 26 0
          50201101 . 20 26 0
          50201101 . 20 26 0
          50201101 . 20 25 0
          50201101 . 20 25 0
          50201101 . 20 25 0
          50201101 . 20 28 0
          50201101 0 20 35 0
          50201101 . 20 35 0
          50201101 . 20 35 0
          50201101 . 20 35 0
          50201101 . 20 24 0
          50201101 . 20 24 0
          50201101 . 20 26 0
          50201101 . 20 34 0
          50201101 . 20 34 0
          50201101 . 20 35 0
          50201101 . 20 26 0
          50201101 . 20 24 0
          50201101 . 20 32 0
          50201101 . 20 32 0
          50201101 . 20 35 0
          50201101 . 20 22 0
          50201101 . 20 32 0
          50201101 . 20 28 0
          50201101 . 20 28 0
          50201101 . 20 25 0
          50201101 . 20 30 0
          50201101 1 20 29 0
          50201101 . 20 29 0
          50201101 . 20 35 0
          end
          label values sample sample_lbl
          label def sample_lbl 50201101 "Bangladesh 2011", modify
          label values mom_age age_lbl
          label def age_lbl 20 "20", modify
          label def age_lbl 22 "22", modify
          label def age_lbl 23 "23", modify
          label def age_lbl 24 "24", modify
          label def age_lbl 25 "25", modify
          label def age_lbl 26 "26", modify
          label def age_lbl 27 "27", modify
          label def age_lbl 28 "28", modify
          label def age_lbl 29 "29", modify
          label def age_lbl 30 "30", modify
          label def age_lbl 32 "32", modify
          label def age_lbl 34 "34", modify
          label def age_lbl 35 "35", modify
          label def age_lbl 40 "40", modify
          label def age_lbl 45 "45", modify
          Last edited by Veronika Valcikova; 28 Mar 2023, 07:51.

          Comment


          • #6
            You do not need to keep the relevant sample each time you run a regression. You can either use the -bysort- prefix or an -if- restriction.


            Code:
            local predictors_all_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.mom_child_loss_categorical i.mom_cohort
            local predictors_married_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth c.pop_age c.pop_age#c.pop_age i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.pop_edattain2 i.pop_edattain3 i.pop_edattain4 i.mom_cohort i.mom_child_loss_categorical
            bys sample: regress mom_fertility i.FirstDaughter `predictors_all_moms' [pweight=mom_perwt]
            bys sample: regress mom_fertility i.FirstDaughter `predictors_married_moms' [pweight=mom_perwt]
            or


            Code:
            local predictors_all_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.mom_child_loss_categorical i.mom_cohort
            local predictors_married_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth c.pop_age c.pop_age#c.pop_age i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.pop_edattain2 i.pop_edattain3 i.pop_edattain4 i.mom_cohort i.mom_child_loss_categorical
            levelsof sample, local(samples)
            foreach sample of local samples{
                regress mom_fertility i.FirstDaughter `predictors_all_moms' if `sample'== sample [pweight=mom_perwt] 
                regress mom_fertility i.FirstDaughter `predictors_married_moms' if `sample'== sample [pweight=mom_perwt]
            }

            Comment


            • #7
              Dear Andrew
              Thank you!

              As you are already familiar with "my case" I would like to ask you for help with the following issue: I would like to run 100 regressions, 2 regressions per each of the 50 samples and keep only one point estimate (and its significance) - the FirstDaughter coefficient. Again, the independent variables are stored in local macros

              Code:
              ** all:
              local predictors_all_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth i.mom_edattain2 i.mom_edattain3 i.mom_edattain4  i.mom_cohort
              
              *** married:
              local predictors_married_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth c.pop_age c.pop_age#c.pop_age i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.pop_edattain2 i.pop_edattain3 i.pop_edattain4 i.mom_cohort
              I do not know which of the recommended "if" or "bys" ways of computation are suitable. Just to remind, the regressions are as follow:

              for each out of the 50 samples
              run these two regressios

              regress mom_fertility i.FirstDaughter `predictors_all_moms' [pweight=mom_perwt]

              regress mom_fertility i.FirstDaughter `predictors_married_moms' [pweight=mom_perwt]

              but keep only FirstDaughter coefficient from each one of them

              write the FirstDaughter into excel file

              I would like to automatize this as far as possible (but after hours of trying, I still do not know whether it is even possible..)

              Desired output

              All Married

              Bolivia 0.5* 0.6*
              Uganda 0.7*** 0.7
              Morocco 0.7*** 0.7
              Brazil 0.6** 0.4
              France .... ....
              ...
              ...
              ...
              ...
              Peru 0.5* 0.6*
              Note: each number in the table corresponds to the FirstDaughter coefficient.

              Thank you very much!

              Code:
              * Example generated by -dataex-. For more info, type help dataex
              clear
              input long sample byte FirstDaughter int mom_age
              51201101 . 31
              51201101 . 30
              51201101 . 26
              51201101 . 26
              51201101 . 29
              51201101 . 29
              51201101 . 32
              51201101 . 44
              51201101 1 32
              51201101 . 32
              51201101 . 44
              51201101 0 38
              51201101 . 38
              51201101 . 18
              51201101 . 25
              51201101 . 25
              51201101 . 25
              51201101 0 33
              51201101 . 33
              51201101 . 25
              51201101 0 28
              51201101 . 28
              51201101 . 28
              51201101 1 33
              51201101 . 33
              51201101 1 41
              51201101 . 41
              51201101 . 41
              51201101 . 25
              51201101 . 25
              51201101 0 31
              51201101 . 31
              51201101 1 31
              51201101 . 31
              51201101 0 38
              51201101 . 38
              51201101 . 24
              51201101 . 29
              51201101 . 29
              51201101 . 29
              51201101 . 32
              51201101 1 35
              51201101 . 35
              51201101 . 35
              51201101 . 30
              51201101 . 30
              51201101 . 25
              51201101 . 25
              51201101 . 28
              51201101 . 28
              51201101 0 35
              51201101 . 35
              51201101 . 35
              51201101 . 29
              51201101 . 29
              51201101 . 33
              51201101 . 45
              51201101 . 53
              51201101 . 31
              51201101 . 31
              51201101 . 35
              51201101 . 35
              51201101 . 29
              51201101 . 30
              51201101 . 30
              51201101 1 33
              51201101 . 33
              51201101 . 33
              51201101 . 33
              51201101 . 33
              51201101 . 30
              51201101 . 29
              51201101 . 29
              51201101 . 30
              51201101 . 34
              51201101 . 34
              51201101 . 34
              51201101 . 28
              51201101 . 28
              51201101 . 27
              51201101 . 25
              51201101 . 36
              51201101 . 36
              51201101 . 30
              51201101 . 30
              51201101 . 28
              51201101 . 28
              51201101 . 36
              51201101 1 31
              51201101 . 31
              51201101 . 36
              51201101 . 36
              51201101 . 34
              51201101 . 34
              51201101 . 32
              51201101 . 32
              51201101 . 24
              51201101 . 26
              51201101 . 26
              51201101 . 36
              end
              label values sample sample_lbl
              label def sample_lbl 51201101 "Armenia 2011", modify
              label values mom_age age_lbl
              label def age_lbl 18 "18", modify
              label def age_lbl 24 "24", modify
              label def age_lbl 25 "25", modify
              label def age_lbl 26 "26", modify
              label def age_lbl 27 "27", modify
              label def age_lbl 28 "28", modify
              label def age_lbl 29 "29", modify
              label def age_lbl 30 "30", modify
              label def age_lbl 31 "31", modify
              label def age_lbl 32 "32", modify
              label def age_lbl 33 "33", modify
              label def age_lbl 34 "34", modify
              label def age_lbl 35 "35", modify
              label def age_lbl 36 "36", modify
              label def age_lbl 38 "38", modify
              label def age_lbl 41 "41", modify
              label def age_lbl 44 "44", modify
              label def age_lbl 45 "45", modify
              label def age_lbl 53 "53", modify
              Last edited by Veronika Valcikova; 28 Mar 2023, 13:19.

              Comment


              • #8
                This is not tested and requires frames (Stata 16+).

                Code:
                local predictors_all_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.mom_child_loss_categorical i.mom_cohort
                local predictors_married_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth c.pop_age c.pop_age#c.pop_age i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.pop_edattain2 i.pop_edattain3 i.pop_edattain4 i.mom_cohort i.mom_child_loss_categorical
                levelsof sample, local(samples)
                frame create results
                frame results{
                    set obs `=wordcount("`samples'")'
                    gen sample=.
                    gen all=.
                    gen married=.
                }
                local i 0
                foreach sample of local samples{
                    local ++i
                    regress mom_fertility i.FirstDaughter `predictors_all_moms' if `sample'== sample [pweight=mom_perwt]
                    frame results: replace sample= `sample' in `i'
                    frame results: replace all= `=_b[1.FirstDaughter]' in `i'
                    regress mom_fertility i.FirstDaughter `predictors_married_moms' if `sample'== sample [pweight=mom_perwt]
                    frame results: replace married= `=_b[1.FirstDaughter]' in `i'
                }
                frame change results
                export excel using myfile, replace firstrow(variables)

                If you provide a dataex of the sample variable, I can have the output with variable labels instead of their values, e.g., "Bolivia" instead of its numeric code.
                Last edited by Andrew Musau; 28 Mar 2023, 16:54.

                Comment


                • #9
                  Originally posted by Andrew Musau View Post
                  This is not tested and requires frames (Stata 16+).

                  Code:
                  local predictors_all_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.mom_child_loss_categorical i.mom_cohort
                  local predictors_married_moms c.mom_age c.mom_age#c.mom_age c.mom_age_at_birth c.pop_age c.pop_age#c.pop_age i.mom_edattain2 i.mom_edattain3 i.mom_edattain4 i.pop_edattain2 i.pop_edattain3 i.pop_edattain4 i.mom_cohort i.mom_child_loss_categorical
                  levelsof sample, local(samples)
                  frame create results
                  frame results{
                  set obs `=wordcount("`samples'")'
                  gen sample=.
                  gen all=.
                  gen married=.
                  }
                  local i 0
                  foreach sample of local samples{
                  local ++i
                  regress mom_fertility i.FirstDaughter `predictors_all_moms' if `sample'== sample [pweight=mom_perwt]
                  frame results: replace sample= `sample' in `i'
                  frame results: replace all= `=_b[1.FirstDaughter]' in `i'
                  regress mom_fertility i.FirstDaughter `predictors_married_moms' if `sample'== sample [pweight=mom_perwt]
                  frame results: replace married= `=_b[1.FirstDaughter]' in `i'
                  }
                  frame change results
                  export excel using myfile, replace firstrow(variables)

                  If you provide a dataex of the sample variable, I can have the output with variable labels instead of their values, e.g., "Bolivia" instead of its numeric code.
                  Dear Andrew
                  Thank you so much!!

                  First, I am not sure how this can help, but here again, the dataex of sample variable. If this is not what you require, please let me know.

                  Code:
                  * Example generated by -dataex-. For more info, type help dataex
                  clear
                  input long sample
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  50201101
                  end
                  label values sample sample_lbl
                  label def sample_lbl 50201101 "Bangladesh 2011", modify

                  Second, the code stops working at
                  Code:
                   set obs `=wordcount("`samples'")'
                  and it outputs an error message:
                  observation number out of range
                  Observation number must be between 22,029,581 and 2,147,483,619. (Observation numbers
                  are typed without commas.)
                  r(198);
                  Thank you very much for your help! I really appreciate it.

                  Comment


                  • #10
                    The sample codes, however, range from 50 201 101 to 894 201 001.So, I don't see any reason why it should not work. Also, I work with the most recent Stata version - Stata/BE 17.0

                    Comment


                    • #11
                      You need to run the whole code in one go and make sure that the macro samples is defined. Your error message is consistent with

                      Code:
                      set obs 0
                      which can arise if the macro samples is empty from below and thus the count of its elements is 0.

                      levelsof sample, local(samples)

                      Comment


                      • #12
                        Originally posted by Andrew Musau View Post
                        You need to run the whole code in one go and make sure that the macro samples is defined. Your error message is consistent with

                        Code:
                        set obs 0
                        which can arise if the macro samples is empty from below and thus the count of its elements is 0.
                        Dear Andrew

                        The local macro 'samples' is well-defined.

                        Code:
                        levelsof sample, local(samples)
                        
                        50201101 51201101 68201201 72201101 76201001 104201401 116201301 124201101 188201101 192201201 204201301 214201001 218201001 242201401 250201101 275201701 288201001 324201401 348201101 360201001 364201101 372201101 372201601 380201101 480201101 484201001 484201501 504201401 524201101 591201001 608201001 620201101 630201001 642201101 643201001 646201201 686201301 694201501 710201601 716201201 740201201 768201001 780201101 800201401 834201201 840201001 840201501 858201101 894201001

                        Comment


                        • #13
                          Originally posted by Andrew Musau View Post
                          You need to run the whole code in one go and make sure that the macro samples is defined. Your error message is consistent with

                          Code:
                          set obs 0
                          which can arise if the macro samples is empty from below and thus the count of its elements is 0.
                          Dear Andrew
                          Sorry for the inconvenience !

                          It is working now (restarting Stata helped) ! Thank you so much.

                          Comment


                          • #14
                            There is no reason why then you should get the error. You should show the result of running the entire code as below:

                            Code:
                            sysuse auto, clear
                            rename rep78 sample
                            levelsof sample, local(samples)
                            frame create results
                            frame results{
                                set obs `=wordcount("`samples'")'
                                gen sample=.
                                gen all=.
                                gen married=.
                            }
                            Res.:

                            Code:
                            . sysuse auto, clear
                            (1978 Automobile Data)
                            
                            . 
                            . rename rep78 sample
                            
                            . 
                            . levelsof sample, local(samples)
                            1 2 3 4 5
                            
                            . 
                            . frame create results
                            
                            . 
                            . frame results{
                            . 
                            .     set obs `=wordcount("`samples'")'
                            Number of observations (_N) was 0, now 5.
                            . 
                            .     gen sample=.
                            (5 missing values generated)
                            . 
                            .     gen all=.
                            (5 missing values generated)
                            . 
                            .     gen married=.
                            (5 missing values generated)
                            . 
                            . }

                            Comment


                            • #15
                              Originally posted by Andrew Musau View Post
                              There is no reason why then you should get the error. You should show the result of running the entire code as below:

                              Code:
                              sysuse auto, clear
                              rename rep78 sample
                              levelsof sample, local(samples)
                              frame create results
                              frame results{
                              set obs `=wordcount("`samples'")'
                              gen sample=.
                              gen all=.
                              gen married=.
                              }
                              Res.:

                              Code:
                              . sysuse auto, clear
                              (1978 Automobile Data)
                              
                              .
                              . rename rep78 sample
                              
                              .
                              . levelsof sample, local(samples)
                              1 2 3 4 5
                              
                              .
                              . frame create results
                              
                              .
                              . frame results{
                              .
                              . set obs `=wordcount("`samples'")'
                              Number of observations (_N) was 0, now 5.
                              .
                              . gen sample=.
                              (5 missing values generated)
                              .
                              . gen all=.
                              (5 missing values generated)
                              .
                              . gen married=.
                              (5 missing values generated)
                              .
                              . }
                              Dear Andrew
                              Sorry for the inconvenience !

                              It is working now (restarting Stata helped) ! Thank you so much.

                              Comment

                              Working...
                              X