Skip to content

Commit 3bfbb5e

Browse files
matthieugomezeloualiche
authored andcommitted
update to FixedEffects 0.7 (#12)
1 parent 6b47652 commit 3bfbb5e

File tree

8 files changed

+22
-28
lines changed

8 files changed

+22
-28
lines changed

.DS_Store

6 KB
Binary file not shown.

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ FillArrays = "0"
2525
StatsBase = "0"
2626
StatsModels = "0.6"
2727
Tables = "0"
28-
DataFrames = "0.19"
29-
FixedEffects = "0.6"
30-
FixedEffectModels = "0.9, 0.10"
28+
DataFrames = "0.19, 0.20"
29+
FixedEffects = "0.7"
30+
FixedEffectModels = "0.10.3"
3131
LeastSquaresOptim = "0.7"
3232

3333
[extras]

README.md

100755100644
File mode changed.

benchmark/benchmark.md

100755100644
File mode changed.

dataset/Cigar.csv

100755100644
File mode changed.

dataset/EmplUK.csv

100755100644
File mode changed.

src/fit.jl

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ function regife(df, f::FormulaTerm, vcov::CovarianceEstimator = Vcov.simple();
4747
formula = FormulaTerm(f.lhs, tuple(ConstantTerm(1), FixedEffectModels.eachterm(f.rhs)...))
4848
end
4949

50-
formula, formula_endo, formula_iv = FixedEffectModels.decompose_iv(f)
50+
formula, formula_endo, formula_iv = FixedEffectModels.parse_iv(f)
5151

5252
m, formula = parse_interactivefixedeffect(df, formula)
5353
if ifeformula != nothing # remove after depreciation
@@ -114,7 +114,7 @@ function regife(df, f::FormulaTerm, vcov::CovarianceEstimator = Vcov.simple();
114114
has_fes_intercept = true
115115
end
116116
fes = FixedEffect[FixedEffectModels._subset(fe, esample) for fe in fes]
117-
feM = FixedEffectModels.AbstractFixedEffectSolver{Float64}(fes, weights, Val{:lsmr})
117+
feM = FixedEffectModels.AbstractFixedEffectSolver{Float64}(fes, weights, Val{:cpu})
118118
end
119119

120120

@@ -138,7 +138,8 @@ function regife(df, f::FormulaTerm, vcov::CovarianceEstimator = Vcov.simple();
138138
formula_schema = apply_schema(formula, schema(formula, subdf, contrasts), StatisticalModel)
139139

140140
y = convert(Vector{Float64}, response(formula_schema, subdf))
141-
oldy = copy(y)
141+
tss_total = FixedEffectModels.tss(y, has_intercept || has_fes_intercept, weights)
142+
142143
X = convert(Matrix{Float64}, modelmatrix(formula_schema, subdf))
143144

144145
# change default if has_regressors
@@ -158,14 +159,12 @@ function regife(df, f::FormulaTerm, vcov::CovarianceEstimator = Vcov.simple();
158159
coef_names = Symbol.(coef_names)
159160

160161

161-
162+
# demean variables
162163
if has_fes
163164
FixedEffectModels.solve_residuals!(y, feM)
164165
FixedEffectModels.solve_residuals!(X, feM)
165-
end
166-
y .= y .* sqrtw
167-
X .= X .* sqrtw
168-
166+
end
167+
169168

170169

171170
##############################################################################
@@ -178,23 +177,25 @@ function regife(df, f::FormulaTerm, vcov::CovarianceEstimator = Vcov.simple();
178177
idpool = fill(0.1, length(id.pool), m.rank)
179178
timepool = fill(0.1, length(time.pool), m.rank)
180179

180+
y .= y .* sqrtw
181+
X .= X .* sqrtw
181182
if !has_regressors
183+
# factor model
182184
fp = FactorModel(y, sqrtw, id.refs, time.refs, m.rank)
183185
fs = FactorSolution(idpool, timepool)
184-
# factor model
185-
186186
(fs, iterations, converged) =
187187
fit!(Val{method}, fp, fs; maxiter = maxiter, tol = tol, lambda = lambda)
188188
else
189189
# interactive fixed effect
190-
# initialize fs
191190
coef = X \ y
192191
fp = FactorModel(y - X * coef, sqrtw, id.refs, time.refs, m.rank)
193192
fs = FactorSolution(idpool, timepool)
194193
fit!(Val{:levenberg_marquardt}, fp, fs; maxiter = 100, tol = 1e-3, lambda = lambda)
195194

196195
fs = InteractiveFixedEffectsSolution(coef, fs.idpool, fs.timepool)
197196
fp = InteractiveFixedEffectsModel(y, sqrtw, X, id.refs, time.refs, m.rank)
197+
198+
198199
ym = copy(y)
199200
Xm = copy(X)
200201

@@ -206,15 +207,14 @@ function regife(df, f::FormulaTerm, vcov::CovarianceEstimator = Vcov.simple();
206207
# y ~ x + γ1 x factors + γ2 x loadings
207208
# if not, this means fit! ended up on a a local minimum.
208209
# restart with randomized coefficients, factors, loadings
209-
newfeM = FixedEffectModels.AbstractFixedEffectSolver{Float64}(getfactors(fp, fs), weights, Val{:lsmr})
210-
ym .= ym ./sqrtw
210+
newfeM = FixedEffectModels.AbstractFixedEffectSolver{Float64}(getfactors(fp, fs), weights, Val{:cpu})
211+
ym .= ym ./ sqrtw
211212
FixedEffectModels.solve_residuals!(ym, newfeM, tol = tol, maxiter = maxiter)
212213
ym .= ym .* sqrtw
213-
214-
Xm .= Xm ./sqrtw
214+
Xm .= Xm ./ sqrtw
215215
FixedEffectModels.solve_residuals!(Xm, newfeM, tol = tol, maxiter = maxiter)
216216
Xm .= Xm .* sqrtw
217-
ydiff = Xm * (fs.b - Xm \ ym)
217+
ydiff = Xm * (fs.b - Xm \ ym)
218218
if iterations >= maxiter || norm(ydiff) <= 0.01 * norm(y)
219219
break
220220
end
@@ -264,13 +264,12 @@ function regife(df, f::FormulaTerm, vcov::CovarianceEstimator = Vcov.simple();
264264
# compute various r2
265265
nobs = sum(esample)
266266
rss = sum(abs2, residualsm)
267-
_tss = FixedEffectModels.tss(ym, has_intercept || has_fes_intercept, sqrtw)
267+
_tss = FixedEffectModels.tss(ym ./ sqrtw, has_intercept || has_fes_intercept, weights)
268268
r2_within = 1 - rss / _tss
269269

270270
rss = sum(abs2, residuals)
271-
_tss = FixedEffectModels.tss(oldy, has_intercept || has_fes_intercept, sqrtw)
272-
r2 = 1 - rss / _tss
273-
r2_a = 1 - rss / _tss * (nobs - has_intercept) / dof_residual
271+
r2 = 1 - rss / tss_total
272+
r2_a = 1 - rss / tss_total * (nobs - has_intercept) / dof_residual
274273
end
275274

276275
##############################################################################

test/interactivefixedeffectsmodel.jl

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,6 @@ for method in [:levenberg_marquardt, :dogleg]
100100
@test norm(result.coef ./ [ -2.62105, -0.0470005] .- 1) < precision
101101
end
102102

103-
# Check old syntax still works
104-
df[!, :pState] = categorical(df.State)
105-
df[!, :pYear] = categorical(df.Year)
106-
model = @model Sales ~ Price ife = (pState + pYear, 2) fe = pState
107-
result = regife(df, model)
108103

109104
# Check formula can be constructed programatically
110105
using StatsModels

0 commit comments

Comments
 (0)