Skip to content

Commit

Permalink
Fix bug with constant in fixed effects
Browse files Browse the repository at this point in the history
Before, the first fixed effect included the constant. This was changed
in v5 so the constant is on its own in b[_cons], and the saved fixed
effect coefs adjusted for that.

However, if there were other regressors, the fixed effects still
included the constants by mistake.

Also see #140
  • Loading branch information
sergiocorreia committed Aug 2, 2018
1 parent b9379ba commit e39a058
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/reghdfe.ado
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*! version 5.2.6 01aug2018
*! version 5.2.7 02aug2018

program reghdfe, eclass
* Intercept old+version
Expand Down
7 changes: 5 additions & 2 deletions src/reghdfe.sthlp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{smcl}
{* *! version 5.2.6 01aug2018}{...}
{* *! version 5.2.7 02aug2018}{...}
{vieweralsosee "[R] areg" "help areg"}{...}
{vieweralsosee "[R] xtreg" "help xtreg"}{...}
{vieweralsosee "[R] ivregress" "help ivregress"}{...}
Expand All @@ -10,7 +10,7 @@
{vieweralsosee "reg2hdfe" "help reg2hdfe"}{...}
{vieweralsosee "a2reg" "help a2reg"}{...}
{viewerjumpto "Syntax" "reghdfe##syntax"}{...}
{viewerjumpto "Description" "reghdfe##description"}{...}
{viewerjumpto "description" "reghdfe##description"}{...}
{viewerjumpto "Options" "reghdfe##options"}{...}
{viewerjumpto "Postestimation Syntax" "reghdfe##postestimation"}{...}
{viewerjumpto "Remarks" "reghdfe##remarks"}{...}
Expand Down Expand Up @@ -702,6 +702,9 @@ on the other hand, there may be alternatives:
{synopt:{cmd:e(df_m)}}model degrees of freedom{p_end}
{synopt:{cmd:e(df_r)}}residual degrees of freedom{p_end}

{synopt:{cmd:e(report_constant)}}whether _cons was included in the regressions (default)
or as part of the fixed effects{p_end}

{synoptset 24 tabbed}{...}
{syntab:Macros}
{synopt:{cmd:e(cmd)}}{cmd:reghdfe}{p_end}
Expand Down
4 changes: 3 additions & 1 deletion src/reghdfe_class.mata
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,9 @@ class FixedEffects
st_global("e(title3)", text)
}
if (!missing(sumweights)) st_numscalar("e(sumweights)", sumweights)
if (!missing(sumweights)) st_numscalar("e(sumweights)", sumweights)
st_numscalar("e(report_constant)", compute_constant & report_constant)
// ---- .options properties ---------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions src/reghdfe_store_alphas.ado
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ program define reghdfe_store_alphas, eclass
if (e(rank)) {
qui _predict double `d' if e(sample), xb
}
else if (e(report_constant)) {
gen double `d' = _b[_cons]
}
else {
gen double `d' = 0
}
Expand Down
53 changes: 44 additions & 9 deletions test/alphas.do
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,60 @@ noi cscript "reghdfe: saving alphas (FEs)" adofile reghdfe
* [TEST] Non-missing alphas
gen double turn2 = turn
reghdfe turn2, a(TURN=turn) keepsing v(-1)
assert abs(TURN - turn) < 1e-12
assert abs(turn - TURN - _b[_cons]) < 1e-12
drop turn2 TURN


* [TEST] One FE
areg price weight gear, absorb(turn)
loc c = _b[_cons]
predict double bench_d if e(sample), d
*replace bench_d = bench_d + `c' if e(sample) // Now both areg and reghdfe save demeaned FEs
predict double D0 if e(sample), d

reghdfe price weight gear, absorb(FE=turn) keepsing v(-1)
gen double d1 = FE
gen double D1 = FE

reghdfe price weight gear, absorb(turn, save) keepsing v(-1)
gen double d2 = __hdfe1__
gen double D2 = __hdfe1__

gen delta1 = reldif(D0, D1)
gen delta2 = reldif(D0, D2)

gen delta1 = reldif(bench_d, d1)
gen delta2 = reldif(bench_d, d2)
su D*

assert(delta1 < 1e-10)
assert(delta2 < 1e-10)
drop delta* D* FE __*


* [TEST] One FE, no regressors
* SEE: https://github.com/sergiocorreia/reghdfe/issues/140

areg price, absorb(turn)
predict double D0 if e(sample), d

reghdfe price, absorb(FE=turn) keepsing v(-1)
gen double D1 = FE

reghdfe price, absorb(turn, save) keepsing v(-1)
gen double D2 = __hdfe1__

gen delta1 = reldif(D0, D1)
gen delta2 = reldif(D0, D2)

su D*

assert(delta1 < 1e-10)
assert(delta2 < 1e-10)
drop delta* D* FE __*


* [TEST] Several FEs, all should have mean zero
reghdfe price weight length gear, a(foreign turn trunk rep, save) tol(1e-16)
foreach var of varlist __hdfe* {
su `var'
assert(abs(r(mean)) < 1e-7) // this is actually good precision, as price has mean of 6,000
}
drop __hdfe*

drop bench_* delta* d1 d2 FE __*

* [TEST] One FE with MVs
areg price weight gear, absorb(rep)
Expand Down Expand Up @@ -68,7 +100,9 @@ noi cscript "reghdfe: saving alphas (FEs)" adofile reghdfe

drop bench* delta* fe*


* [TEST] Slope

reg price ibn.turn#c.gear, nocons
predict double bench_slope, xb

Expand All @@ -79,6 +113,7 @@ noi cscript "reghdfe: saving alphas (FEs)" adofile reghdfe
assert(delta < 1e-8)
drop delta bench_slope slope


* [TEST] Several slopes
areg price ibn.turn#c.(gear disp), a(turn)
predict double bench_slopes, xb
Expand Down
2 changes: 2 additions & 0 deletions test/report_constant.do
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ noi cscript "reghdfe: test that the constant option does not change anything" ad
local absvars turn

local exclude ///
scalar: report_constant ///
matrix: b V ///
macros: indepvars cmdline


* [TEST] Unadjusted
reghdfe `lhs' `rhs', absorb(`absvars') keepsingletons verbose(-1) constant
trim_cons
Expand Down

0 comments on commit e39a058

Please sign in to comment.