Search code examples
loopsstatastata-macros

Append local macro in Stata


In Stata, I want to explore regressions with many combinations of different dependent and independent variables.

For this, I decided to use a loop that does all these regressions, and then saves the relevant results (coefficients, R2, etc.) in a matrix in a concise and convenient form.

For this matrix, I want to name rows and columns to make reading easier.

Here is my code so far:

clear
sysuse auto.dta
set more off

scalar i = 1

foreach v in price mpg {
foreach w in weight length {

    quietly: reg `v' `w' foreign

local result_`v'_`w'_b = _b[`w']
local result_`v'_`w'_t = ( _b[`w'] / _se[`w'] )
local result_`v'_`w'_r2 = e(r2)

if scalar(i) == 1 {
mat A = `result_`v'_`w'_b', `result_`v'_`w'_t', `result_`v'_`w'_r2'
local rownms: var label `v'
}
if i > 1 {
mat A = A \ [`result_`v'_`w'_b', `result_`v'_`w'_t', `result_`v'_`w'_r2']
*local rownms: `rownms' "var label `v'"
}

scalar i = i+1

}
}

mat coln A = b t r2
mat rown A = `rownms'

matrix list A

It will give a resulting matrix A that looks like this:

. matrix list A

A[4,3]
                b           t          r2
Price   3.3207368   8.3882744    .4989396
Price   90.212391   5.6974982   .31538316
Price  -.00658789  -10.340218   .66270291
Price  -.22001836  -9.7510366   .63866239

Clearly, there is something not quite finished yet. The row names of the matrix should be "price, price, mpg, mpg" because that is what the dependent variable is in the four regressions.

In the code above, consider the now-commented-out line

*local rownms: `rownms' "var label `v'"

It is commented out because in the current form, it gives an error.

I wish to append the local macro rownms with the label (or name) of the variable on every iteration, producing Price Price Mileage (MPG) Mileage (MPG).

But I cannot seem to get the quotes right to append the macro with the label of the current variable.


Solution

  • Matrix row and column names are limited in what they can hold. In general, variable labels won't be very suitable.

    Here is some simpler code.

    sysuse auto.dta, clear 
    
    matrix drop A 
    local rownms 
    
    foreach v in price mpg {
        foreach w in weight length {
            quietly: reg `v' `w' foreign
            mat A = nullmat(A) \ (_b[`w'], _b[`w']/_se[`w'],  e(r2))  
            local rownms `rownms' `v':`w'
        }
    }
    
    mat coln A = b t r2
    mat rown A = `rownms'
    
    matrix list A
    

    Notes:

    1. The nullmat() trick removes the need for a branch of the code on first and later runs through.

    2. Putting results into locals and then taking them out again is not needed. To get out of the habit, think of this analogy. You have a pen in your hand. You put it in a box. You take it out again. Now you have a pen in your hand. Why do the box thing if you don't need to?

    This works with your example, but the results are not very good.

     local rownms `rownms' "`: var label `v''"