Stata: saving regressions coefficients and standar

2019-09-05 16:37发布

问题:

I would like to run several regressions and store their results in a DTA file that I could later use for analysis. My constraints are:

  1. I cannot install modules (I am writing code for other people and not sure what modules they have installed)
  2. Some of the regressors are factor variables.
  3. Each regression differ only by the dependent variable, so I would like to store that in the final dataset to keep track of what regression the coefficients/variances correspond to.

I am seriously losing sanity here. I feel it's probably simple given that Stata is statistics software but svmat is really not cooperative. Currently what I am doing is this:

sysuse census, clear
generate constant = 1
capture matrix drop regsresults // erase previously existing matrix
foreach depvar in marriage divorce {

    reg `depvar' popurban i.region constant, robust noconstant  // regressions
    matrix result_matrix = e(b)\vecdiag(e(V))                   // grab coeffs and their variances in a 2xK matrix
    matrix rownames result_matrix = `depvar'_b `depvar'_v       // add rownames to the two extra rows
    matrix regsresults = nullmat(regsresults)\result_matrix     // add those results matrix to the existing ones

}
matrix list regsresults
clear 
svmat regsresults, names(col)

This creates for each regression: one row that stores the coefficients, one row that stores their variance using vecdiag(e(V)). The row names for those two rows are the dependent variable name, followed by _b for coeffs and _v for variances.

I use a manual constant because _cons is not a valid name for a variable when using svmat.

Of course my "solution" does not work because factor levels generate strange matrix column names which are then invalid variable names when calling svmat. (The error is a terse invalid syntax.) I'd be happy with ANY solution to overcome that problem, given my constraints. It doesn't have to use svmat, coefficients and variances can be on same line if it makes it easier, etc.

回答1:

Renaming matrix columns is one option:

sysuse census, clear
generate constant = 1
capture matrix drop regsresults // erase previously existing matrix
foreach depvar in marriage divorce {

    reg `depvar' popurban i.region constant, robust noconstant  // regressions
    matrix result_matrix = e(b)\vecdiag(e(V))                   // grab coeffs and their variances in a 2xK matrix
    matrix rownames result_matrix = `depvar'_b `depvar'_v       // add rownames to the two extra rows
    matrix regsresults = nullmat(regsresults)\result_matrix     // add those results matrix to the existing ones

}
matrix list regsresults
matname regsresults reg1 reg2 reg3 reg4, columns(2..5) explicit

clear 
svmat regsresults, names(col)

For more complex namelists (reg1 - reg4), you can build the syntax beforehand, store in a local, and then use with matname.

Edit

The same strategy, with some automatation. It uses macro extended functions for matrices. See help extended_fcn.

sysuse census, clear
generate constant = 1
capture matrix drop regsresults // erase previously existing matrix
foreach depvar in marriage divorce {

    reg `depvar' popurban i.region constant, robust noconstant  // regressions
    matrix result_matrix = e(b)\vecdiag(e(V))                   // grab coeffs and their variances in a 2xK matrix
    matrix rownames result_matrix = `depvar'_b `depvar'_v       // add rownames to the two extra rows
    matrix regsresults = nullmat(regsresults)\result_matrix     // add those results matrix to the existing ones

}

// list the matrix
matrix list regsresults

// get original column names of matrix
local names : colfullnames regsresults

// get original row names of matrix (and row count)
local rownames : rowfullnames regsresults
local c : word count `rownames'

// make original names legal variable names
local newnames
foreach name of local names {
    local newnames `newnames' `=strtoname("`name'")'
}

// rename columns of matrix
matrix colnames regsresults = `newnames'

// convert matrix to dataset
clear 
svmat regsresults, names(col)

// add matrix row names to dataset
gen rownames = ""
forvalues i = 1/`c' {
    replace rownames = "`:word `i' of `rownames''" in `i'
}

// list
order rownames
list, noobs

See also ssc describe matnames.



回答2:

Just for completeness, using Roberto excellent solution, this is the final code:

sysuse census, clear
generate constant = 1
capture matrix drop regsresults // erase previously existing matrix
replace region = region +15
foreach depvar in marriage divorce {

    reg `depvar' popurban i.region constant, robust noconstant  // regressions
    matrix result_matrix = e(b)\vecdiag(e(V))                   // grab coeffs and their variances in a 2xK matrix
    matrix rownames result_matrix = `depvar'_b `depvar'_v       // add rownames to the two extra rows
    matrix regsresults = nullmat(regsresults)\result_matrix     // add those results matrix to the existing ones

}

matrix list regsresults
local rownames : rownames regsresults           // collects row names
local colnames : colfullnames regsresults       // collects column names
local newnames                                  // clean column names
foreach name of local colnames {
    local newnames `newnames' `=strtoname("`name'")'
}
matrix colnames regsresults = `newnames'        // attribute the cleaned column names

clear 
svmat regsresults, names(col)

// add the row names as its own variable rown
gen str rown = ""
order rown, 
local i = 1
foreach rowname in `rownames' {
    replace rown = "`rowname'" if _n == `i'
    local i = `i' + 1
}
br