*qrprocess_p: predict for the quantile regression process *! version 1.1.1 14.04.2020 Blaise Melly program define qrprocess_p version 6, missing /* Step 1: place command-unique options in local myopts Note that standard options are LR: Index XB Cooksd Hat REsiduals RSTAndard RSTUdent STDF STDP STDR noOFFset SE: Index XB STDP noOFFset */ local myopts "RESIDuals Difference REArranged(numlist >0 <1 min=1 sort) cdf(numlist min=1 sort)" /* Step 2: call _propts, exit if done, else collect what was returned. */ _pred_me "`myopts'" `0' if `s(done)' { exit } local vtyp `s(typ)' local varn `s(varn)' local 0 `"`s(rest)'"' /* Step 3: Parse your syntax. */ syntax [if] [in] [, `myopts' noOFFset EQuation(string)] if "`rearranged'"!=""{ local cfg="rearrangement" } else if "`cdf'"!=""{ local cfg="rcdf" } if "`equatio'" == "" { /* we're version 6 -- 7-char locals! */ tempname b mat `b' = get(_b) local eqnames : coleq `b' gettoken equatio : eqnames } /* Step 4: Concatenate switch options together */ local type "`residua'`differe'`cfg'" /* Step 5: quickly process default case if you can Do not forget -nooffset- option. */ if "`type'"=="" | "`type'"=="xb"{ tempname quant mat `quant'=e(quantiles) if "`type'"=="" { di in smcl in gr "(option xb assumed; fitted values)" } if "`equation'"==""{ local equation "#1" } local nq=wordcount("`equation'") if `nq'>1{ forvalues i=1/`nq'{ local names "`names' `varn'`i'" } } else{ local names "`varn'" } tokenize "`equation'", parse(" ") foreach name of local names{ local eqnum=substr("`1'",2,100) local temp=`quant'[`eqnum',1] _predict `vtyp' `name' `if' `in', xb `offset' equation(`1') label var `name' "0.`temp' QR fitted values" mac shift } exit } /* Step 6: mark sample (this is not e(sample)). */ marksample touse if "`type'"=="rearrangement" { tempname quants local nq=wordcount("`rearranged'") if `nq'>1{ forvalues i=1/`nq'{ quietly gen `vtyp' `varn'`i'=. local pn "`pn' `varn'`i'" } tokenize "`rearranged'", parse(" ") local i=1 while "`1'" != "" { matrix `quants'=nullmat(`quants')\(`1') mac shift local i=`i'+1 } } else{ quietly gen `vtyp' `varn'=. local pn "`varn'" matrix `quants'=`rearranged' } mata: rearranged("`e(xvar)'","`touse'","`quants'","`pn'") if `nq'==1 { di "Rearranged `rearranged' conditional quantile function" } else{ dis "Rearranged conditional quantile functions for the following quantiles:" forvalues i=1/`nq'{ local temp=`quants'[`i',1] dis "The `temp' conditional quantile is saved in `varn'`i'" } } exit } if "`type'"=="rcdf" { tempname eval local nq=wordcount("`cdf'") if `nq'>1{ forvalues i=1/`nq'{ quietly gen `vtyp' `varn'`i'=. local pn "`pn' `varn'`i'" } tokenize "`cdf'", parse(" ") local i=1 while "`1'" != "" { matrix `eval'=nullmat(`eval')\(`1') mac shift local i=`i'+1 } } else{ quietly gen `vtyp' `varn'=. local pn "`varn'" matrix `eval'=`cdf' } mata: rcdf("`e(xvar)'","`touse'","`eval'","`pn'") if `nq'==1 { di "Conditional CDF at `e(depvar)'=`cdf'." } else{ dis "Conditional CDFs at the following values of `e(depvar)':" forvalues i=1/`nq'{ local temp=`eval'[`i',1] dis "CDF at `e(depvar)'=`temp' is saved in `varn'`i'" } } exit } /* Step 7: handle options that take argument one at a time. Comment if restricted to e(sample). Be careful in coding that number of missing values created is shown. Do all intermediate calculations in double. */ /* Step 8: handle switch options that can be used in-sample or out-of-sample one at a time. Be careful in coding that number of missing values created is shown. Do all intermediate calculations in double. */ if "`type'"=="residuals" { tempvar xb qui _predict double `xb' if `touse', xb `offset' eq(`equatio') gen `vtyp' `varn' = `e(depvar)'-`xb' if `touse' label var `varn' "Residuals: `equatio'" exit } tokenize "`equatio'", parse(",") local eq1 `"`1'"' local eq2 `"`3'"' if "`type'"=="difference" { tempvar xb1 xb2 qui _predict double `xb1' if `touse', `offset' eq(`eq1') qui _predict double `xb2' if `touse', `offset' eq(`eq2') gen `vtyp' `varn' = `xb1' - `xb2' if `touse' lab var `varn' "Fitted diff.: `eq1' - `eq2'" exit } /* Step 9: handle switch options that can be used in-sample only. Same comments as for step 8. */ *qui replace `touse'=0 if !e(sample) /* Step 10. Issue r(198), syntax error. The user specified more than one option */ error 198 end *Mata function doing the rearrangement version 9.2 mata void rearranged(string scalar reg, string scalar touse, string scalar quant_wished, string scalar out) { real colvector quants, pred_quants, q_index real scalar nw, i, n real matrix x, coef, fit quants=st_matrix("e(quantiles)") pred_quants=st_matrix(quant_wished) nw=rows(pred_quants) q_index=J(nw,1,.) for(i=1;i<=nw;i++){ // if(min(abs(quants:-pred_quants[i]))>0.000001){ // "The "+strofreal(pred_quants[i])+"th quantile was not included in the estimation." // "Include this quantile when you call qrprocess if you want ot obtaint the predicted values at this quantile." // exit(400) // } q_index[i,1]=sum(quants:<=pred_quants[i]) } if(reg!=""){ x=st_data(.,tokens(reg),touse) n=rows(x) x=x,J(n,1,1) } else { n=sum(st_data(.,touse)) x=J(n,1,1) } coef=st_matrix("e(coefmat)") fit=cross(x',coef)' for(i=1;i<=n;i++){ fit[.,i]=sort(fit[.,i],1) } st_store(.,tokens(out),touse,fit[q_index,.]') } *Mata function calculating the cdf mata void rcdf(string scalar reg, string scalar touse, string scalar eval, string scalar out) { real colvector quants, evalu real scalar nw, n, i, j real matrix x, coef, fit, cdf quants=st_matrix("e(quantiles)") evalu=st_matrix(eval) nw=rows(evalu) if(reg!=""){ x=st_data(.,tokens(reg),touse) n=rows(x) x=x,J(n,1,1) } else { n=sum(st_data(.,touse)) x=J(n,1,1) } coef=st_matrix("e(coefmat)") fit=cross(x',coef) cdf=J(n,nw,.) for(i=1;i<=n;i++){ for(j=1;j<=nw;j++){ cdf[i,j]=quants[max(sum(fit[i,.]:<=evalu[j,1])\1),1] } } st_store(.,tokens(out),touse,cdf) }