1 Star 1 Fork 2

连享会/lassopack

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
rlasso.ado 43.96 KB
一键复制 编辑 原始数据 按行查看 历史
kahrens 提交于 2020-12-12 19:01 . update version numbers in header
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264
*! rlasso 1.0.11 29jul2020
*! lassopack package 1.4.1
*! authors aa/cbh/ms
* Also see lassoutils.ado notes for details of code updates.
* Updates (release date):
* 1.0.05 (30jan2018)
* First public release.
* Added seed(.) option to rlasso/lassoutils to control rnd # seed for xdep & sup-score.
* Fixed bug in DisplayCoefs (didn't accommodate both e(notpen) and e(pnotpen)).
* Promoted to require version 13 or higher.
* Added dots option.
* Fixed displaynames bug (wrong dictionaries used for partialled-out vars).
* Recoding of cons and demeaning flags.
* partial and nocons no longer compatible.
* Removed hdm version of sup-score stat.
* Removed misc debug code.
* 1.0.06 (10feb2018)
* Support for Sergio Correia's FTOOLS FE transform (if installed).
* 1.0.07 (29aug2018)
* Added support for string cluster variable.
* Added support for aweights and pweights (equivalent) by preweighting.
* Fixed display bug when no penalized or unpenalized vars selected.
* 1.0.08 (26nov2018)
* Added saved value of objective function (pmse for lasso, prmse for sqrt-lasso).
* Added two undocumented options: sigma(.) to override lasso estimation of initial sigma
* and ssiid to override use of multiplier bootstrap for sup-score test.
* changed "partial" to "PARtial" option
* 1.0.09 (11dec2018)
* Added support for combination of partial(.) + nocons
* Bug fix that would cause exit with error if cluster + no penalized vars.
* 1.0.10 (13jan2019)
* Replaced pols option with ols option; fixed reporting of e(estimator) macro; more use of flag macros.
* Replace Ups terminology with Psi (penalty loadings). Dropped usage of gammad.
* Bug fix - FE + weights would fail if data were not sorted on xtset panel var.
* 1.0.11 (29july2020)
* Added e(r2), e(cmdline); support for 2-way clustering; norecover option; psolver(.) option.
*
* to do - noftools + weights
program rlasso, eclass sortpreserve
version 13
syntax [anything] [if] [in] [aw pw] ///
[, ///
displayall ///
varwidth(int 17) ///
VERsion ///
supscore ///
testonly ///
* ///
]
local lversion 1.0.11
local pversion 1.4.0
if "`version'" != "" { // Report program version number, then exit.
di in gr "rlasso version `lversion'"
di in gr "lassopack package version `pversion'"
ereturn clear
ereturn local version `lversion'
ereturn local pkgversion `pversion'
exit
}
if ~replay() { // not replay so estimate
_rlasso `anything' ///
`if' `in' [`weight' `exp'], ///
`options' `supscore' `testonly'
}
else if e(cmd)~="rlasso" { // replay, so check that rlasso results exist
di as err "last estimates not found"
exit 301
}
if "`e(method)'"~="" {
DisplayCoefs, `displayall' varwidth(`varwidth')
}
// temp measure
if e(supscore) < . {
DisplaySupScore
}
end
program _rlasso, eclass sortpreserve
version 13
syntax varlist(numeric fv ts min=2) ///
[aw pw/] [if] [in] ///
[, ///
/// specify options with varlists to be used by marksample/markout
PNOTPen(varlist fv ts numeric) /// list of variables not penalised
PARtial(string) /// string so that list can contain "_cons"
NORecover /// don't recover partialled-out coeffs
fe /// do within-transformation
NOCONStant ///
CLuster(varlist max=2) /// penalty level/loadings allow for within-panel dependence & heterosk.
ols /// post-lasso coefs in e(b) (default=lasso)
pols /// legacy option (equivalent to ols)
prestd ///
dm /// treat data as having zero mean (for debugging use)
VERbose /// pass to lassoutils
VVERbose /// pass to lassoutils
dots ///
displaynames_o(string) /// dictionary with names of vars as supplied in varlist
displaynames_d(string) /// corresponding display names of vars
pminus(int 0) /// overrides calculation of pminus
debug /// used for debugging
postall /// full coef vector in e(b) (default=selected only)
testonly /// obtain supscore test only
NOFTOOLS ///
psolver(string) /// optional choice of solver for partialling-out
* /// additional options
]
// save at beginning, return at the end
local cmdline `0'
*** rlasso-specific
// to distinguish between lasso2 and rlasso treatment of notpen,
// rlasso option is called pnotpen
// to keep lasso2 and rlasso code aligned, rename to notpen here
// and at end of program save macros as pnotpen
// temporary measure until lasso2 and rlasso code is merged
local notpen `pnotpen'
// flags
local olsflag =("`ols'`pols'"~="") // pols is a legacy option equivalent to ols
local testonlyflag =("`testonly'"~="")
local debugflag =("`debug'"~="")
local postallflag =("`postall'"~="")
local feflag=("`fe'"~="")
*
*** Record which observations have non-missing values
marksample touse
if `feflag' {
cap xtset
local ivar `r(panelvar)'
}
markout `touse' `varlist' `cluster' `ivar', strok
sum `touse' if `touse', meanonly
local N = r(N)
*
*** FEs. Create 1/0 flag.
if `feflag' {
if "`ivar'"=="" {
di as err "Error: fe option requires data to be xtset"
exit 459
}
// fe transformation may expect data to be sorted on ivar
local sortvar : sortedby
local sortvar : word 1 of `sortvar' // in case sorted on multiple variables
if "`ivar'"~="`sortvar'" {
di as text "(sorting by xtset panelvar `ivar')"
sort `ivar'
}
}
*
*** prestd flag
// nb: if model has constant, prestd will demean (i.e. partial it out)
local prestdflag =("`prestd'"~="")
*
*** weight flag
local weightflag =("`weight'"~="")
*
*** constant, partial, etc.
// conmodel: constant in original model
// consflag: constant in transformed equation to estimate
// dmflag: treat data as zero-mean
if `weightflag' & ("`noconstant'"~="") {
// incompatible options - with weights, must have a constant to partial out or remove by FE
di as err "incompatible options - weights + noconstant"
exit 198
}
local consmodel =("`noconstant'"=="")
if `feflag' {
local consmodel 0 // if fe, then consmodel=0 always
}
// model with weights must have a constant before partialling out or FE transformation
// weighting implies special treatment of constant - must be partialled-out
// will be automatic if fe
if `weightflag' & ~`feflag' {
local partial `partial' _cons // duplicate _cons not a problem since removed below
}
local partialflag =("`partial'"~="") // =1 even if just cons is being partialled out
// tell estimation code if cons will have been partialled out or there isn't one in the first place
// note that prestandardizing always implies the constant, if present, is to be calculated by the calling program
if `feflag' | `partialflag' | `prestdflag' | (`consmodel'==0) {
local consflag 0
}
else {
local consflag 1
}
// "_cons" allowed as an argument to partial(.) - remove it
local partial : subinstr local partial "_cons" "", all word count(local pconscount)
local notpen : subinstr local notpen "_cons" "", all word count(local notpenconscount)
if "`dm'"~="" {
// dmflag tells estimation code to treat data as zero-mean; user can force this with dm option
local dmflag 1
}
else if `consmodel' {
// model has an constant that will be partialled out or treated as unpenalized
local dmflag 0
}
else {
// special case - nocons and no FEs means treat vars as if demeaned
local dmflag 1
}
// ignore norecover if no partialled-out variables
local parrflag = ("`norecover'"=="") & (`partialflag' | `prestdflag')
*
*** weights ***
// create weight variable wvar
if `weightflag' {
// pw = aw + robust ... and more commands allow aw
local wtexp `"[aw=`exp']"'
tempvar wvar
qui gen double `wvar'=`exp'
sum `wvar' if `touse' `wtexp', meanonly
if r(min)<0 {
di as err "error - negative weights encountered"
exit 101
}
// Weight statement
di as text "(sum of wgt is " %14.4e `r(sum_w)' ")"
// normalize to have unit mean
qui replace `wvar' = `wvar' * `N'/r(sum_w)
}
if "`weight'"=="pweight" {
// pw => robust
local options `options' robust
local options : list uniq options
}
*
*** create variable used for getting lags etc. in Mata
tempvar tindex
qui gen `tindex'=1 if `touse'
qui replace `tindex'=sum(`tindex') if `touse'
*** create main varlist and tempvars
// remove duplicates from varlist
// _o list is vars with original names
fvexpand `varlist' if `touse'
local varlist_o `r(varlist)'
// check for duplicates has to follow expand
local dups : list dups varlist_o
if "`dups'"~="" {
di as text "Dropping duplicates: `dups'"
}
local varlist_o : list uniq varlist_o
*
*** Create separate _o varlists: Y, X, notpen, partial
// Y, X
local varY_o : word 1 of `varlist_o'
local varX_o : list varlist_o - varY_o // incl notpen/partial
// notpen
fvexpand `notpen' if `touse'
local notpen_o `r(varlist)'
local dups : list dups notpen_o
if "`dups'"~="" {
di as text "Dropping duplicates: `dups'"
}
local notpen_o : list uniq notpen_o
// partial
fvexpand `partial' if `touse'
local partial_o `r(varlist)'
local dups : list dups partial_o
if "`dups'"~="" {
di as text "Dropping duplicates: `dups'"
}
local partial_o : list uniq partial_o
// "model" = vars without partialled-out
local varXmodel_o : list varX_o - partial_o
*
*** syntax checks
// check that notpen vars are in full list
local checklist : list notpen_o - varX_o
local checknum : word count `checklist'
if `checknum' {
di as err "syntax error - `checklist' in notpen(.) but not in list of regressors"
exit 198
}
// check that partial vars are in full list
local checklist : list partial_o - varX_o
local checknum : word count `checklist'
if `checknum' {
di as err "syntax error - `checklist' in partial(.) but not in list of regressors"
exit 198
}
// check that ivar (FE) is not a used variable
if `feflag' {
fvrevar `varY_o' `varX_o', list // list option means we get only base vars
local vlist `r(varlist)'
local checklist : list ivar - vlist
local checknum : word count `checklist'
if `checknum'==0 {
di as err "syntax error - `ivar' is xtset variable and cannot be used in model"
exit 198
}
}
// other checks
if `pconscount' & `feflag' {
di as err "error: incompatible options, partial(_cons) and fe"
exit 198
}
if `feflag' & "`noconstant'"~="" {
di as err "error: incompatible options, fe and nocons"
exit 198
}
*
*** Create _t varlists: Y, X, notpen, partial
// _o list is vars with original names
// _t list is temp vars if transform needed, original vars if not
if `feflag' | `weightflag' { // everything needs to be transformed including partial
local temp_ct : word count `varlist_o'
mata: s_maketemps(`temp_ct')
local varlist_t `r(varlist)'
}
else if `partialflag' | `prestdflag' { // everything except partial_o needs to be transformed
local varYXmodel_o `varY_o' `varXmodel_o'
local temp_ct : word count `varYXmodel_o'
mata: s_maketemps(`temp_ct')
local varYXmodel_t `r(varlist)'
matchnames "`varlist_o'" "`varYXmodel_o'" "`varYXmodel_t'"
local varlist_t `r(names)'
}
else { // no transformation needed but still need temps
fvrevar `varlist_o' if `touse' // fvrevar creates temps only when needed
local varlist_t `r(varlist)'
}
// dictionary is now varlist_o / varlist_t
// now create separate _o and _t varlists using dictionary
foreach vlist in varY varX varXmodel notpen partial {
matchnames "``vlist'_o'" "`varlist_o'" "`varlist_t'"
local `vlist'_t `r(names)' // corresponding tempnames; always need this because of possible fvs
}
*
******************* Display names ***********************************************************
// may be called by another program with tempvars and display names for them
// if display names option not used, use _o names as provided in rlasso command
// if display names option used, use display names matched with _o names
// if display names macros are empty, has no effect
matchnames "`varY_o'" "`displaynames_o'" "`displaynames_d'"
local varY_d `r(names)'
matchnames "`varXmodel_o'" "`displaynames_o'" "`displaynames_d'"
local varXmodel_d `r(names)'
matchnames "`varX_o'" "`displaynames_o'" "`displaynames_d'"
local varX_d `r(names)'
matchnames "`notpen_o'" "`displaynames_o'" "`displaynames_d'"
local notpen_d `r(names)'
matchnames "`partial_o'" "`displaynames_o'" "`displaynames_d'"
local partial_d `r(names)'
*
*** summary varlists and flags:
* varY_o = dep var
* varY_t = dep var, temp var
* varX_o = full, expanded set of RHS, original names, includes partial
* varX_t = as above but with temp names for all variables
* varXmodel_o = full, expanded set of RHS, original names, excludes partial
* varXmodel_t = as above but with temp names for all variables
* notpen_o = full, expanded set of not-penalized
* notpen_t = as above but with temp names for all variables
// p is number of penalized vars in the model; follows convention in BCH papers
// p is calculated in lassoutils/_rlasso as number of model vars excluding constant
// here we calculate which of the model vars are unpenalized or omitted/base vars
// to provide as `pminus' to lassoutils/_rlasso (unless provided by user)
// do here so that code above is compatible with lasso2
// use _o names / display names since they have info on whether var is omitted/base/etc.
if ~`pminus' {
foreach vn of local varXmodel_d { // display names
_ms_parse_parts `vn'
// increment pminus if model variable is MISSING
if r(omit) {
local ++pminus
}
}
foreach vn of local notpen_d { // display names
_ms_parse_parts `vn'
// increment pminus if notpen variable is NOT MISSING
if ~r(omit) {
local ++pminus
}
}
}
// p0 here is total number of variables provided to model EXCLUDING constant
local p0 : word count `varXmodel_o'
local p =`p0'-`pminus'
// warn
if `p'<=0 {
di as text "warning: no penalized variables; estimates are OLS"
}
// now for error-checking below, p0 should INCLUDE constant unless partialled-out etc.
local p0 =`p0'+`consflag'
*
******************* FE, partialling out, standardization, weighting *****************************
// varX are all X vars including partial
// varXmodel are model vars excluding partial
// FE transform applies to varX; incorporates weighting in FE transform but does not weight transformed vars.
// Partialling applies to varXmodel; same treatment of weights and vars as with FE.
// Weights transform applies to varXmodel after possible FE/partial; multiplies vars by sqrt(wvar).
// Prestd transform applies to varX model after possible FE/partial/weighting; standardizes vars.
// If FE: partial-out FEs from Xmodel temp variables, then preserve,
// then partial-out low-dim ctrls from temp variables
// restore will restore all temp vars with only FEs partialled-out
// If no FE: leave original variables unchanged.
// partial-out low-dim ctrls from Xmodel temp variables.
// if no FE/low-dim ctrls, no transform needed
// NB: unpartial routine expects unweighted vars and recovers partialled-out coeffs from weighted OLS.
// hence with FE, preserve after FE transformation but before weighting.
if `feflag' { // FE-transform all variables including those to partial-out
// first FE transformation
fvrevar `varY_o' `varX_o' if `touse' // in case any FV or TS vars in _o list
local vlist `r(varlist)'
local vlist_t `varY_t' `varX_t' // everything including partialling Xs
lassoutils `vlist', /// call on _o list
touse(`touse') ///
tvarlist(`vlist_t') /// initialize _t vars
wvar(`wvar') /// weighted demeaning but vars left unweighted
`noftools' ///
fe(`ivar') // triggers branching to FE utility
local dmflag =1 // data are now demeaned
local N_g =r(N_g) // N_g will be empty if no FEs
local noftools `r(noftools)' // either not installed or user option
// now partialling-out if any
if `partialflag' { // And then partial out any additional vars
preserve // preserve the original values of tempvars before partialling out
local vlist `varY_t' `varXmodel_t' // model vars have been FE-transformed already
local vlist_t `varY_t' `varXmodel_t' // corresponding temp vars
local pvlist `partial_t' // partial vars have been FE-transformed already
lassoutils `vlist', ///
touse(`touse') /// don't need tvarlist because vars already created
tvarlist(`vlist_t') /// overwrite these (were initialized by FE utility)
partial(`pvlist') /// partial vars are already FE-transformed
partialflag(`partialflag') /// triggers branching to partial utility
wvar(`wvar') /// weight vars if necessary
psolver(`psolver') /// optional choice of solver
dmflag(1) // FE => data already demeaned
}
if `weightflag' { // applies only to Y and Xmodel vars
lassoutils `varY_t' `varXmodel_t', /// _t vars have been created and filled so use here
touse(`touse') /// don't need tvarlist because vars already created
tvarlist(`varY_t' `varXmodel_t') /// overwrite these (were initialized by FE utility)
wvar(`wvar') // triggers branching to weighting utility
}
if `prestdflag' { // applies only to Y and Xmodel vars
tempname prestdY prestdX
lassoutils `varY_t', /// _t vars have been created and filled so use here
touse(`touse') /// don't need tvarlist because vars already created
tvarlist(`varY_t') /// overwrite this (was initialized by FE utility)
std ///
dmflag(1) // FE => data already demeaned
mat `prestdY'=r(stdvec)
lassoutils `varXmodel_t', ///
touse(`touse') ///
tvarlist(`varXmodel_t') /// overwrite this (was initialized by FE utility)
std ///
dmflag(1) // FE => data already demeaned
mat `prestdX'=r(stdvec)
}
}
else if `partialflag' { // no FE but partial out from Y and Xmodel vars
// always enter with weights unless no cons in model
fvrevar `varY_o' `varXmodel_o' if `touse' // in case any FV or TS vars in _o list
local vlist `r(varlist)' // Y and Xmodel _o lists after fvrevar-ing
local vlist_t `varY_t' `varXmodel_t' // corresponding temp vars; Y and Xmodel only
fvrevar `partial_o' if `touse' // in case any FV or TS vars in _o list
local pvlist `r(varlist)' // partial_o list after fvrevar-ing
lassoutils `vlist', /// apply to Y and Xmodel_o list after fvrevar-ing
touse(`touse') ///
partial(`pvlist') /// use partial_o list after fvrevar-ing
wvar(`wvar') /// use weights when partialling out
tvarlist(`vlist_t') /// initialize the tempvars
partialflag(`partialflag') /// triggers branching to partial utility
psolver(`psolver') /// optional choice of solver
dmflag(`dmflag') // treat data as not yet demeaned unless nocons
local dmflag =1 // data are now demeaned
if `weightflag' { // initialized tempvars now need to be weighted by sqrt(wvar)
lassoutils `vlist_t', /// applies to Y and Xmodel only
touse(`touse') ///
tvarlist(`vlist_t') /// overwrite these
wvar(`wvar') // triggers branching to weighting utility
}
if `prestdflag' { // applies to Y and Xmodel only
tempname prestdY prestdX
lassoutils `varY_t', /// apply to varY_t vars (already initialized by partialling)
touse(`touse') ///
tvarlist(`varY_t') /// overwrite _t var
std ///
dmflag(1) // partial => data already demeaned
mat `prestdY'=r(stdvec)
lassoutils `varXmodel_t', /// apply to varXmodel_t vars (already initialized by partialling)
touse(`touse') ///
tvarlist(`varXmodel_t') /// overwrite _t vars
std ///
dmflag(1) // partial => data already demeaned
mat `prestdX'=r(stdvec)
}
}
else if `weightflag' & `prestdflag' { // should not enter here since weights => constant => partial
di as err "internal rlasso error - weightflag+prestdflag"
exit 499
}
else if `prestdflag' { // nothing partialled out so varXmodel = varX
// data are unweighted
tempname prestdY prestdX
fvrevar `varY_o' if `touse' // first standardize varY
local vlist `r(varlist)' // varY_o list after fvrevar-ing
local vlist_t `varY_t' // corresponding temp var
lassoutils `vlist', ///
touse(`touse') ///
std ///
tvarlist(`vlist_t') /// initialize these
consmodel(`consmodel') ///
dmflag(`dmflag') // data not mean zero unless overridden by user
mat `prestdY'=r(stdvec)
fvrevar `varXmodel_o' if `touse' // now standardize varXmodel_o
local vlist `r(varlist)' // varXmodel_o list after fvrevar-ing
local vlist_t `varXmodel_t' // corresponding temp vars
lassoutils `vlist', ///
touse(`touse') ///
std ///
tvarlist(`vlist_t') /// initialize these
consmodel(`consmodel') ///
dmflag(`dmflag') // data not mean zero unless overridden by user
mat `prestdX'=r(stdvec)
}
else if `weightflag' { // nothing partialled out, no std, varXmodel=varX
// only reach here if no constant (since cons is partialled out)
fvrevar `varY_o' `varXmodel_o' if `touse' // in case any FV or TS vars in _o list
local vlist `r(varlist)' // _o list after fvrevar-ing
local vlist_t `varY_t' `varXmodel_t' // corresponding temp vars
lassoutils `vlist', /// call on _o list after fvrevar-ing
touse(`touse') ///
tvarlist(`vlist_t') /// initialize the tempvars
wvar(`wvar') // triggers branching to weighting utility
}
************* Partialling/standardization END ***********************************************
************* Lasso estimation with transformed/partialled-out vars *************************
if "`verbose'`vverbose'`dots'"=="" {
local quietly "quietly" // don't show lassoutils output
}
`quietly' lassoutils `varY_t', ///
rlasso /// branch to _rlasso subroutine
/// nocons, no penloads, etc. all assumed
touse(`touse') ///
xnames_o(`varXmodel_d') /// display names for lassoutils output
xnames_t(`varXmodel_t') ///
cluster(`cluster') ///
notpen_o(`notpen_d') ///
notpen_t(`notpen_t') ///
consflag(`consflag') /// =0 if cons already partialled out or if no cons
dmflag(`dmflag') /// =1 if data have been demeaned
pminus(`pminus') ///
stdy(`prestdY') ///
stdx(`prestdX') ///
tindex(`tindex') /// variable used for time-series lags etc.
`verbose' `vverbose' `dots' ///
`testonly' ///
`options'
*
************* Finish up ********************************************************
*** e-return lasso estimation results
tempname b beta betaOLS Psi sPsi ePsi
tempname betaAll betaAllOLS
tempname lambda slambda lambda0 rmse rmseOLS objfn r2
tempname c gamma
tempname supscore supscore_p supscore_cv supscore_gamma
if ~`testonlyflag' {
if "`cluster'" ~= "" {
local N_clust =r(N_clust)
local N_clust1 =r(N_clust1)
local N_clust2 =r(N_clust2)
}
mat `beta' =r(beta) // may be empty!
mat `betaOLS' =r(betaOLS) // may be empty!
mat `betaAll' =r(betaAll)
mat `betaAllOLS' =r(betaAllOLS)
mat `Psi' =r(Psi)
mat `sPsi' =r(sPsi)
mat `ePsi' =r(ePsi)
scalar `lambda' =r(lambda)
scalar `slambda' =r(slambda)
scalar `lambda0' =r(lambda0)
scalar `c' =r(c)
scalar `gamma' =r(gamma)
scalar `rmse' =r(rmse) // Lasso RMSE
scalar `rmseOLS' =r(rmseOLS) // post-Lasso RMSE
scalar `r2' =r(r2)
scalar `objfn' =r(objfn)
local selected `r(selected)' // EXCL NOTPEN/CONS
local selected0 `r(selected0)' // INCL NOTPEN, EXCL CONS
local s =r(s) // EXCL NOTPEN/CONS; number of elements in selected
local s0 =r(s0) // INCL NOTPEN, EXCL CONS; number of elements in selected0
local clustvar `r(clustvar)'
local robust `r(robust)'
local center =r(center)
local method `r(method)' // lasso or sqrt-lasso
local niter =r(niter)
local maxiter =r(maxiter)
local npsiiter =r(npsiiter)
local maxpsiiter =r(maxpsiiter)
// these can be missings
scalar `supscore' =r(supscore)
scalar `supscore_p' =r(supscore_p)
scalar `supscore_cv' =r(supscore_cv)
scalar `supscore_gamma' =r(supscore_gamma)
local ssnumsim =r(ssnumsim)
// for HAC and 2-way cluster lasso
local bw =r(bw) // will overwrite existing bw macro
local kernel `r(kernel)' // will overwrite existing kernel macro
local psinegs =r(psinegs)
local psinegvars `r(psinegvars)'
// remove duplicates
local psinegvars : list uniq psinegvars
// flag for empty beta (consflag=0 means rlasso didn't estimate a constant)
local betaempty =(`s0'==0 & `consflag'==0)
// error check
if `betaempty' {
if ~(colsof(`beta')==1 & `beta'[1,1]==.) {
di as err "internal _rlasso error - beta should be empty (no vars estimated) but isn't
exit 499
}
}
// issue warning if lasso max iteration limit hit
if `niter'==`maxiter' {
di as text "Warning: reached max shooting iterations w/o achieving convergence."
}
// issue warning if negative penalty loadings encountered
if `psinegs' {
di as text "Warning: `psinegs' negative penalty loadings encountered/adjusted."
di as text "Variables affected: `psinegvars'"
}
// error check - p0s and ps should match
if `p0'~=r(p0) { // number of all variables in betaAll INCL NOTPEN/CONS (if present or not partialled etc.)
di as err "internal _rlasso error - p0 count of model vars `p0' does not match returned value `r(p0)'"
exit 499
}
if `p'~=r(p) { // number of penalized variables in model
di as err "internal _rlasso error - p count of penalized vars `p' does not match returned value `r(p)'"
exit 499
}
// fix depvar (rownames) of beta vectors to use _o (or _d if display names provided) not _t
mat rownames `beta' = `varY_d'
mat rownames `betaOLS' = `varY_d'
mat rownames `betaAll' = `varY_d'
mat rownames `betaAllOLS' = `varY_d'
if ~`betaempty' { // cnames should stay empty if beta has a single missing value
local cnames_o : colnames `beta'
fvstrip `cnames_o' // colnames may insert b/n/o operators - remove
local cnames_o `r(varlist)'
matchnames "`cnames_o'" "`varlist_o'" "`varlist_t'"
local cnames_t `r(names)'
}
else {
local cnames_o
local cnames_t
}
*
*********** Get coeff estimates for partialled-out vars/std intercept. ********************
if `feflag' & `partialflag' { // FE case and there are partialled-out notpen vars
restore // Restores dataset with tempvars after FE transform but before notpen partialled out
}
if (`partialflag' | (`prestdflag' & `consmodel')) & (`parrflag') { // standardization removes constant so must enter for that
if `feflag' {
local depvar `varY_t' // use FE-transformed depvar and X vars before any weighting
local scorevars `cnames_t'
local partialvars `partial_t'
}
else {
local depvar `varY_o' // use original depvar and X vars
local scorevars `cnames_o'
local partialvars `partial_o'
}
lassoutils `depvar', ///
unpartial ///
touse(`touse') ///
beta(`beta') ///
scorevars(`scorevars') ///
partial(`partialvars') ///
wvar(`wvar') /// unpartial routine expects UNWEIGHTED vars + weight vector
names_o(`varX_d') /// dictionary
names_t(`varX_t') /// dictionary
consmodel(`consmodel')
mat `beta' = r(b)
mat `betaAll' = `betaAll', r(bpartial)
lassoutils `depvar', ///
unpartial ///
touse(`touse') ///
beta(`betaOLS') ///
scorevars(`scorevars') ///
partial(`partialvars') ///
wvar(`wvar') ///
names_o(`varX_d') /// dictionary
names_t(`varX_t') /// dictionary
consmodel(`consmodel')
mat `betaOLS' = r(b)
mat `betaAllOLS' = `betaAllOLS', r(bpartial)
// for unknown reasons, _ms_build_info doesn't add info here (e.g. "base")
_ms_build_info `beta' if `touse'
_ms_build_info `betaAll' if `touse'
_ms_build_info `betaOLS' if `touse'
_ms_build_info `betaAllOLS' if `touse'
// finish by setting betaempty to 0
local betaempty =0
}
*
*** Prepare and post results
if ~`olsflag' & ~`postallflag' { // selected lasso coefs by default
mat `b' = `beta'
}
else if `olsflag' & ~`postallflag' { // selected post-lasso coefs
mat `b' = `betaOLS'
}
else if ~`olsflag' { // full lasso coef vector
mat `b' = `betaAll'
}
else { // full post-lasso coef vector
mat `b' = `betaAllOLS'
}
if `betaempty' & ~`postallflag' { // no vars in b
ereturn post , obs(`N') depname(`varY_d') esample(`touse') // display name
}
else { // b has some selected/nonpen/cons
ereturn post `b', obs(`N') depname(`varY_d') esample(`touse') // display name
}
// additional returned results
ereturn local noftools `noftools'
ereturn local postall `postall'
ereturn scalar niter =`niter'
ereturn scalar maxiter =`maxiter'
ereturn scalar npsiiter =`npsiiter'
ereturn scalar maxpsiiter =`maxpsiiter'
ereturn local robust `robust'
ereturn local ivar `ivar'
ereturn local selected `selected' // selected only
ereturn local varXmodel `varXmodel_d' // display name
ereturn local varX `varX_d' // display name
if `olsflag' {
ereturn local estimator ols
}
else {
ereturn local estimator `method'
}
ereturn local method `method'
ereturn local predict rlasso_p
ereturn local cmd rlasso
ereturn local cmdline `"rlasso `cmdline'"'
ereturn scalar center =`center'
ereturn scalar cons =`consmodel'
ereturn scalar lambda =`lambda'
ereturn scalar lambda0 =`lambda0'
ereturn scalar slambda =`slambda'
ereturn scalar c =`c'
ereturn scalar gamma =`gamma'
// HAC or 2-way cluster lasso (neg loadings possible)
ereturn local psinegs =`psinegs'
ereturn local psinegvars `psinegvars'
ereturn scalar bw =`bw'
ereturn local kernel `kernel'
if `supscore' < . {
ereturn scalar ssnumsim =`ssnumsim'
ereturn scalar supscore =`supscore'
ereturn scalar supscore_p =`supscore_p'
ereturn scalar supscore_cv =`supscore_cv'
ereturn scalar supscore_gamma =`supscore_gamma'
}
if "`N_clust'" ~= "" {
ereturn local clustvar `clustvar'
ereturn scalar N_clust =`N_clust'
if `N_clust2'>0 & `N_clust2'<. {
ereturn scalar N_clust1 =`N_clust1'
ereturn scalar N_clust2 =`N_clust2'
}
}
if "`N_g'" ~= "" {
ereturn scalar N_g =`N_g'
}
ereturn scalar fe =`feflag'
ereturn scalar rmse =`rmse'
ereturn scalar rmseOLS =`rmseOLS'
ereturn scalar r2 =`r2'
if "`method'"=="sqrt-lasso" {
ereturn scalar prmse =`objfn'
}
else {
ereturn scalar pmse =`objfn'
}
ereturn scalar pminus =`pminus'
ereturn scalar p =`p' // number of all penalized vars; excludes omitteds etc.
ereturn scalar s0 =`s0' // number of all estimated coefs (elements of beta)
ereturn scalar s =`s' // number of selected
ereturn matrix sPsi =`sPsi'
ereturn matrix ePsi =`ePsi'
ereturn matrix Psi =`Psi'
ereturn matrix betaAllOLS =`betaAllOLS'
ereturn matrix betaAll =`betaAll'
ereturn matrix betaOLS =`betaOLS'
ereturn matrix beta =`beta'
// rlasso-specific:
// selected0 and s0 included partialled-out.
// If cons exists and was not partialled out, add to notpen and selected0.
// Otherwise if cons exists and was partialled out, add to to partial list.
if `consmodel' & ~`partialflag' {
local selected0 `selected0' _cons
local notpen_d `notpen_d' _cons // display name
}
else if `consmodel' & `partialflag' {
local partial_d `partial_d' _cons // display name
local selected0 `selected0' `partial_d' // display name
}
else if `partialflag' {
local selected0 `selected0' `partial_d' // display name
}
// remaining results
ereturn local selected0 `selected0'
ereturn local partial `partial_d' // display name
ereturn scalar partial_ct =`: word count `partial_d'' // (display name) number of partialled-out INCLUDING CONSTANT
ereturn scalar s0 =`: word count `selected0'' // (update) selected or notpen, INCL CONS
// rlasso-specific - save as "pnotpen" (vs lasso2 "notpen")
ereturn local pnotpen `notpen_d' // display name
ereturn scalar pnotpen_ct =`: word count `notpen_d'' // (display name) number of notpen INCLUDING CONSTANT (if not partialled-out)
*
}
else {
// sup-score test only - no lasso results
ereturn clear
ereturn scalar N =r(N)
if "`N_clust'" ~= "" {
ereturn local clustvar `clustvar'
ereturn scalar N_clust =`N_clust'
if `N_clust2'>0 & `N_clust2'<. {
ereturn scalar N_clust1 =`N_clust1'
ereturn scalar N_clust2 =`N_clust2'
}
}
if "`N_g'" ~= "" {
ereturn scalar N_g =`N_g'
}
ereturn scalar gamma =r(gamma)
ereturn scalar c =r(c)
ereturn scalar p =`p'
ereturn scalar ssnumsim =r(ssnumsim)
ereturn scalar supscore =r(supscore)
ereturn scalar supscore_p =r(supscore_p)
ereturn scalar supscore_cv =r(supscore_cv)
ereturn scalar supscore_gamma =r(supscore_gamma)
// HAC or 2-way cluster lasso (neg loadings possible)
// for HAC and 2-way cluster lasso
ereturn local psinegs =r(psinegs)
local psinegvars `r(psinegvars)'
// remove duplicates
local psinegvars : list uniq psinegvars
ereturn local psinegvars `psinegvars'
ereturn local cmd rlasso
ereturn scalar cons =`consmodel'
}
end
prog DisplaySupScore
di
di as text "{help rlasso##supscore:Sup-score} test H0: beta=0"
di as text "CCK sup-score statistic" _col(25) as res %6.2f e(supscore) _c
if e(supscore_p) < . {
di as text _col(32) "p-value=" _col(39) as res %6.3f e(supscore_p)
}
else {
di
}
di as text "CCK " as res 100*e(supscore_gamma) as text "% critical value" _c
di as res _col(25) %6.2f e(supscore_cv) _col(32) as text "(asympt bound)"
end
// Used in rlasso and lasso2.
// version 2017-12-20
// updated 31dec17 to accommodate e(pnotpen)
// updated 27july20 to accommodate norecover
prog DisplayCoefs
syntax , ///
[ ///
displayall /// full coef vector in display (default=selected only)
varwidth(int 17) ///
]
local cons =e(cons)
if colsof(e(betaAll)) > e(p) {
local partial `e(partial)'
local partial_ct =e(partial_ct)
}
else {
local partial
local partial_ct =0
}
// varlists
local selected `e(selected)'
fvstrip `selected'
local selected `r(varlist)'
local notpen `e(notpen)'`e(pnotpen)'
fvstrip `notpen'
local notpen `r(varlist)'
local selected0 `e(selected0)'
fvstrip `selected0'
local selected0 `r(varlist)'
// coef vectors
tempname beta betaOLS
if "`displayall'"~="" { // there must be some vars specified even if nothing selected
mat `beta' =e(betaAll)
mat `betaOLS' =e(betaAllOLS)
local col_ct =colsof(`beta')
local vlist : colnames `beta'
local vlistOLS : colnames `betaOLS'
local baselevels baselevels
}
else if e(s0)>0 { // display only selected, but only if there are any
mat `beta' =e(beta)
mat `betaOLS' =e(betaOLS)
local col_ct =colsof(`beta')
local vlist : colnames `beta'
local vlistOLS : colnames `betaOLS'
}
else { // nothing selected, zero columns in beta
local col_ct =0
}
if e(s0)>0 {
_ms_build_info `beta' if e(sample)
_ms_build_info `betaOLS' if e(sample)
}
*** (Re-)display coefficients including constant/partial
local varwidth1 =`varwidth'+1
local varwidth3 =`varwidth'+3
local varwidth4 =`varwidth'+4
local varwidthm7 =`varwidth'-7
local varwidthm13 =`varwidth'-13
di
di as text "{hline `varwidth1'}{c TT}{hline 32}"
if "`e(method)'"=="sqrt-lasso" {
di as text _col(`varwidthm7') "Selected {c |} Sqrt-lasso Post-est OLS"
}
else if "`e(method)'"=="ridge" {
di as text _col(`varwidthm7') "Selected {c |} Ridge Post-est OLS"
}
else if "`e(method)'"=="elastic net" {
di as text _col(`varwidthm7') "Selected {c |} Elastic net Post-est OLS"
di as text _col(`varwidthm7') " {c |}" _c
di as text " (alpha=" _c
di as text %4.3f `e(alpha)' _c
di as text ")"
}
else if "`e(method)'"=="lasso" {
di as text _col(`varwidthm7') "Selected {c |} Lasso Post-est OLS"
}
else {
di as err "internal DisplayCoefs error. unknown method."
exit 1
}
di as text "{hline `varwidth1'}{c +}{hline 32}"
local anynotpen = 0
local i 1
local lastcol = `col_ct' - `partial_ct'
tokenize `vlist' // put elements of coef vector into macros 1, 2, ...
while `i' <= `lastcol' {
local vn ``i''
fvstrip `vn' // get rid of o/b/n prefix for display purposes
local vn `r(varlist)'
_ms_display, element(`i') matrix(`beta') width(`varwidth') `baselevels'
// in selected or notpen list?
local isselnotpen : list posof "`vn'" in selected0
local isnotpen : list posof "`vn'" in notpen
local anynotpen = `anynotpen' + `isnotpen'
// note attached? base, empty, omitted
qui _ms_display, element(`i') matrix(`beta')
local note `r(note)'
qui _ms_display, element(`i') matrix(`betaOLS')
local noteOLS `r(note)'
// if notpen, add footnote
if `isnotpen' & "`note'"=="" {
di as text "{helpb rlasso##notpen:*}" _c
}
if `isselnotpen' {
// lasso coef
if "`note'"=="" {
di _col(`varwidth4') as res %15.7f el(`beta',1,`i') _c
}
else {
di _col(`varwidth4') as text %15s "`note'" _c
}
// post-lasso coef - can be omitted if collinear
if "`noteOLS'"=="" {
di as res %15.7f el(`betaOLS',1,`i')
}
else {
di as text %15s "`noteOLS'"
}
}
else if "`note'"=="(omitted)" {
// not selected
di _col(`varwidth4') as text %15s "(not selected)" _c
di as text %15s "(not selected)"
}
else {
// other eg base var
di as text %15s "`note'" _c
di as text %15s "`noteOLS'"
}
local ++i
}
if `partial_ct' {
di as text "{hline `varwidth1'}{c +}{hline 32}"
di as text _col(`varwidthm13') "Partialled-out{help lasso2##notpen:*}{c |}"
di as text "{hline `varwidth1'}{c +}{hline 32}"
local i = `lastcol'+1
while `i' <= `col_ct' {
local vn ``i''
fvstrip `vn' // get rid of o/b/n prefix for display purposes
local vn `r(varlist)'
_ms_display, element(`i') matrix(`beta') width(`varwidth') `baselevels'
// note attached? base, empty, omitted
qui _ms_display, element(`i') matrix(`beta')
local note `r(note)'
qui _ms_display, element(`i') matrix(`betaOLS')
local noteOLS `r(note)'
// lasso coef
if "`note'"=="" {
di _col(`varwidth4') as res %15.7f el(`beta',1,`i') _c
}
else {
di _col(`varwidth4') as text %15s "`note'" _c
}
// post-lasso coef - can be omitted if collinear
if "`noteOLS'"=="" {
di as res %15.7f el(`betaOLS',1,`i')
}
else {
di as text %15s "`noteOLS'"
}
local ++i
}
}
di as text "{hline `varwidth1'}{c BT}{hline 32}"
if `anynotpen' {
di "{help rlasso##notpen:*Not penalized}"
}
end
*************************** Stata utilities ******************************
// internal version of fvstrip 1.01 ms 24march2015
// takes varlist with possible FVs and strips out b/n/o notation
// returns results in r(varnames)
// optionally also omits omittable FVs
// expand calls fvexpand either on full varlist
// or (with onebyone option) on elements of varlist
program define fvstrip, rclass
version 11.2
syntax [anything] [if] , [ dropomit expand onebyone NOIsily ]
if "`expand'"~="" { // force call to fvexpand
if "`onebyone'"=="" {
fvexpand `anything' `if' // single call to fvexpand
local anything `r(varlist)'
}
else {
foreach vn of local anything {
fvexpand `vn' `if' // call fvexpand on items one-by-one
local newlist `newlist' `r(varlist)'
}
local anything : list clean newlist
}
}
foreach vn of local anything { // loop through varnames
if "`dropomit'"~="" { // check & include only if
_ms_parse_parts `vn' // not omitted (b. or o.)
if ~`r(omit)' {
local unstripped `unstripped' `vn' // add to list only if not omitted
}
}
else { // add varname to list even if
local unstripped `unstripped' `vn' // could be omitted (b. or o.)
}
}
// Now create list with b/n/o stripped out
foreach vn of local unstripped {
local svn "" // initialize
_ms_parse_parts `vn'
if "`r(type)'"=="variable" & "`r(op)'"=="" { // simplest case - no change
local svn `vn'
}
else if "`r(type)'"=="variable" & "`r(op)'"=="o" { // next simplest case - o.varname => varname
local svn `r(name)'
}
else if "`r(type)'"=="variable" { // has other operators so strip o but leave .
local op `r(op)'
local op : subinstr local op "o" "", all
local svn `op'.`r(name)'
}
else if "`r(type)'"=="factor" { // simple factor variable
local op `r(op)'
local op : subinstr local op "b" "", all
local op : subinstr local op "n" "", all
local op : subinstr local op "o" "", all
local svn `op'.`r(name)' // operator + . + varname
}
else if"`r(type)'"=="interaction" { // multiple variables
forvalues i=1/`r(k_names)' {
local op `r(op`i')'
local op : subinstr local op "b" "", all
local op : subinstr local op "n" "", all
local op : subinstr local op "o" "", all
local opv `op'.`r(name`i')' // operator + . + varname
if `i'==1 {
local svn `opv'
}
else {
local svn `svn'#`opv'
}
}
}
else if "`r(type)'"=="product" {
di as err "fvstrip error - type=product for `vn'"
exit 198
}
else if "`r(type)'"=="error" {
di as err "fvstrip error - type=error for `vn'"
exit 198
}
else {
di as err "fvstrip error - unknown type for `vn'"
exit 198
}
local stripped `stripped' `svn'
}
local stripped : list retokenize stripped // clean any extra spaces
if "`noisily'"~="" { // for debugging etc.
di as result "`stripped'"
}
return local varlist `stripped' // return results in r(varlist)
end
// Internal version of matchnames
// Sample syntax:
// matchnames "`varlist'" "`list1'" "`list2'"
// takes list in `varlist', looks up in `list1', returns entries in `list2', called r(names)
program define matchnames, rclass
version 11.2
args varnames namelist1 namelist2
local k1 : word count `namelist1'
local k2 : word count `namelist2'
if `k1' ~= `k2' {
di as err "namelist error"
exit 198
}
foreach vn in `varnames' {
local i : list posof `"`vn'"' in namelist1
if `i' > 0 {
local newname : word `i' of `namelist2'
}
else {
* Keep old name if not found in list
local newname "`vn'"
}
local names "`names' `newname'"
}
local names : list clean names
return local names "`names'"
end
// Display varlist with specified indentation
program define Disp
version 11.2
syntax [anything] [, _col(integer 15) ]
local maxlen = 80-`_col'
local len = 0
local first = 1
foreach vn in `anything' {
* Don't display if base or omitted variable
_ms_parse_parts `vn'
if ~`r(omit)' {
local vnlen : length local vn
if `len'+`vnlen' > `maxlen' {
di
local first = 1
local len = `vnlen'
}
else {
local len = `len'+`vnlen'+1
}
if `first' {
local first = 0
di in gr _col(`_col') "`vn'" _c
}
else {
di in gr " `vn'" _c
}
}
}
* Finish with a newline
di
end
version 13
mata:
void s_maketemps(real scalar p)
{
(void) st_addvar("double", names=st_tempname(p), 1)
st_global("r(varlist)",invtokens(names))
}
// END MATA SECTION
end
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/arlionn/lassopack.git
git@gitee.com:arlionn/lassopack.git
arlionn
lassopack
lassopack
master

搜索帮助