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:
- I cannot install modules (I am writing code for other people and not
sure what modules they have installed)
- Some of the regressors are factor variables.
- 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.
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
.
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