From e85184646d61a8dcad0bebe360efb96a712d3456 Mon Sep 17 00:00:00 2001 From: droodman Date: Sun, 12 Feb 2023 23:48:25 -0500 Subject: [PATCH] WRE jk bug fixes --- Project.toml | 2 +- src/WRE.jl | 13 ++++++------- src/estimators.jl | 12 ++++++------ src/init.jl | 1 + 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Project.toml b/Project.toml index e580861..95c7f22 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "WildBootTests" uuid = "65c2e505-86ba-4c19-93f1-95506c1443d5" authors = ["droodman "] -version = "0.9.0" +version = "0.9.1" [deps] Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" diff --git a/src/WRE.jl b/src/WRE.jl index 8a5489a..bda30af 100644 --- a/src/WRE.jl +++ b/src/WRE.jl @@ -16,8 +16,6 @@ function InitWRE!(o::StrBootTest{T}) where T o.Repl.kZ>1 && (o.numer_b = Vector{T}(undef,nrows(o.Repl.RRpar))) - o.not2SLS = o.liml || !o.robust || !isone(o.κ) # sometimes κ ≠ 1? - if o.willfill o.J⋂s = Array{T,3}(undef, o.N⋂, o.ncolsv, o.Repl.kZ) o.ARpars = Array{T,3}(undef, o.Repl.kZ, o.ncolsv, o.q) @@ -134,8 +132,6 @@ function InitWRE!(o::StrBootTest{T}) where T end end else - o.Repl.Zperp = o.DGP.Zperp = Matrix{T}(undef,0,0) # drop this potentially large array - o.Π̈Rpar = Matrix{T}(undef, o.DGP.kX, o.Repl.kZ) o.invXXS✻XU₂ = Array{T,3}(undef, o.DGP.kX, o.N✻, o.kY₂) @@ -187,7 +183,7 @@ function InitWRE!(o::StrBootTest{T}) where T o.CT✻FEZ = crosstabFE(o, o.DGP.Z, o.info✻) o.CT✻FEy₁ = crosstabFE(o, o.DGP.y₁, o.info✻) o.DGP.restricted && - (o.CT✻FEZR₁ = crosstabFE(o, o.DGP.ZR₁, o.info✻)) + (o.CT✻FEZR₁ = crosstabFE(o, o.DGP.ZR₁, o.info✻)) # XXX just do o.CT✻FEZ * R₁ ? end ((o.willfill) || o.not2SLS) && @@ -331,8 +327,11 @@ function PrepWRE!(o::StrBootTest{T}) where T end if !o.granular + if o.willfill || o.not2SLS + mul!(o.Π̈Rpar, o.DGP.Π̈ , o.Repl.RparY); o.Π̈Rpar[1:o.DGP.kX₁,:] += o.DGP.RperpXperp'o.DGP.RperpXperp \ o.DGP.RperpXperp'o.Repl.RparX + end + if !o.jk # in coarse case, if not jackknifing, construct things while avoiding O(N) operations - mul!(o.Π̈Rpar, o.DGP.Π̈ , o.Repl.RparY); o.Π̈Rpar[1:o.DGP.kX₁,:] += o.DGP.RperpXperp'o.DGP.RperpXperp \ o.DGP.RperpXperp'o.Repl.RparX Π⃛y = [o.DGP.RperpXperp'o.DGP.γ̈X ; zeros(T, o.kX₂, 1)] + o.DGP.Π̈ * o.DGP.γ̈Y t✻!(o.S✻XU₂, o.S✻XX, o.DGP.Π̈); o.S✻XU₂ .= o.S✻XY₂ .- o.S✻XU₂ @@ -422,7 +421,6 @@ function PrepWRE!(o::StrBootTest{T}) where T end end - if o.not2SLS @inbounds for i ∈ 0:o.Repl.kZ, j ∈ 0:i o.S✻ȲUfold[i+1,:,j+1] .= o.S✻ȲU[i+1,j+1] .+ o.S✻ȲU[j+1,i+1] @@ -586,6 +584,7 @@ function FillingLoop2!(o::StrBootTest{T}, dest::Matrix{T}, i::Integer, j::Intege nothing end + # Workhorse for WRE CRVE sandwich filling # Given a zero-based column index, i>0, and a matrix β̈s of all the bootstrap estimates, # return all bootstrap realizations of P_X * Z̄[:,i]_g ' û₁g^*b diff --git a/src/estimators.jl b/src/estimators.jl index 3afd209..096a63d 100644 --- a/src/estimators.jl +++ b/src/estimators.jl @@ -376,11 +376,11 @@ function InitVarsIV!(o::StrEstimator{T}, parent::StrBootTest{T}, Rperp::Abstract o.Xpar₁ = parent.X₁ * o.RperpXperp # X∥ := [Xpar₁ X₂] S✻⋂X₁Zperp = panelcross(o.Xpar₁, o.Zperp, parent.info✻⋂) - ZperpX₁ = sumpanelcross(S✻⋂X₁Zperp)' + !(parent.jk && parent.WREnonARubin) && (ZperpX₁ = sumpanelcross(S✻⋂X₁Zperp)') o.invZperpZperpZperpX₁ = o.invZperpZperp * ZperpX₁ S✻⋂X₂Zperp = panelcross(parent.X₂, o.Zperp, parent.info✻⋂) - ZperpX₂ = sumpanelcross(S✻⋂X₂Zperp)' + !(parent.jk && parent.WREnonARubin) && (ZperpX₂ = sumpanelcross(S✻⋂X₂Zperp)') o.ZperpX = [ZperpX₁ ZperpX₂] o.S✻⋂XZperp = [S✻⋂X₁Zperp; S✻⋂X₂Zperp] @@ -409,12 +409,12 @@ function InitVarsIV!(o::StrEstimator{T}, parent::StrBootTest{T}, Rperp::Abstract o.kX₁ = ncols(X₂X₁) o.S✻⋂ZperpY₂ = panelcross(o.Zperp, parent.Y₂, parent.info✻⋂) - ZperpY₂ = sumpanelcross(o.S✻⋂ZperpY₂) + !(parent.jk && parent.WREnonARubin) && (ZperpY₂ = sumpanelcross(o.S✻⋂ZperpY₂)) o.invZperpZperpZperpY₂ = o.invZperpZperp * ZperpY₂ (parent.NFE>0 && (parent.liml || !isone(parent.κ) || parent.bootstrapt)) && (o.Y₂ = parent.Y₂ - o.Zperp * o.invZperpZperpZperpY₂) o.S✻⋂Zperpy₁ = panelcross(o.Zperp, parent.y₁, parent.info✻⋂) - Zperpy₁ = vec(sumpanelcross(o.S✻⋂Zperpy₁)) + !(parent.jk && parent.WREnonARubin) && (Zperpy₁ = vec(sumpanelcross(o.S✻⋂Zperpy₁))) o.invZperpZperpZperpy₁ = o.invZperpZperp * Zperpy₁ ((parent.NFE>0 && (parent.liml || !isone(parent.κ) || parent.bootstrapt)) || parent.scorebs) && (o.y₁ = parent.y₁ - o.Zperp * o.invZperpZperpZperpy₁) @@ -482,7 +482,8 @@ function InitVarsIV!(o::StrEstimator{T}, parent::StrBootTest{T}, Rperp::Abstract o.twoZR₁y₁ = 2 * vec(sumpanelcross(o.S✻ZR₁y₁)) o.S✻ZR₁ZR₁ = panelcross(o.ZR₁, o.ZR₁, parent.info✻) o.ZR₁ZR₁ = #=Symmetric=#(sumpanelcross(o.S✻ZR₁ZR₁)) - o.ZR₁ .-= o.Zperp * o.invZperpZperpZperpZR₁ + (parent.scorebs || (parent.NFE>0 && !parent.FEboot && o.isDGP && o.restricted && (parent.willfill || parent.not2SLS))) && + (o.ZR₁ .-= o.Zperp * o.invZperpZperpZperpZR₁) t✻minus!(o.X₁ZR₁, o.invZperpZperpZperpX₁', o.ZperpZR₁) t✻minus!(o.X₂ZR₁, o.invZperpZperpZperpX₂', o.ZperpZR₁) o.ZR₁Z -= o.ZperpZR₁'o.invZperpZperp * ZperpZpar @@ -504,7 +505,6 @@ function InitVarsIV!(o::StrEstimator{T}, parent::StrBootTest{T}, Rperp::Abstract (o.ZY₂ = sumpanelcross(o.S✻ZparY₂) - ZperpZpar'o.invZperpZperpZperpY₂) t✻minus!(o.Z, o.Zperp, o.invZperpZperpZperpZpar) - end # end coarse o.V = o.invXX * o.XZ # in 2SLS case, estimator is (V' XZ)^-1 * (V'Xy₁). Also used in k-class and liml robust VCV by Stata convention diff --git a/src/init.jl b/src/init.jl index 1a4b1d9..542a62a 100644 --- a/src/init.jl +++ b/src/init.jl @@ -62,6 +62,7 @@ function Init!(o::StrBootTest{T}) where T # for efficiency when varying r repea o.info✻, o.ID✻ = panelsetupID(o.ID, 1:o.NBootClustVar) end o.willfill = o.robust && o.bootstrapt # will compute sandwich filling for robust denominator? + o.not2SLS = o.liml || !o.robust || !isone(o.κ) # sometimes κ ≠ 1? elseif iszero(o.NClustVar) o.info✻ = [i:i for i in 1:o.Nobs] # causes no collapsing of data in panelsum() calls else