Skip to content

Commit

Permalink
StatsBase -> StatsAPI (#203)
Browse files Browse the repository at this point in the history
* Update FixedEffectModel.jl

StatsBase -> StatsAPI

* Update Project.toml

* Update FixedEffectModels.jl

* Update fit.jl

* Update Project.toml

* Update Project.toml

* Update Project.toml

* Update FixedEffectModel.jl

* Update FixedEffectModel.jl
  • Loading branch information
matthieugomez authored Jun 28, 2022
1 parent 2662649 commit 4887c70
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 33 deletions.
6 changes: 4 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "FixedEffectModels"
uuid = "9d5cd8c9-2029-5cab-9928-427838db53e3"
version = "1.6.7"
version = "1.7.0"

[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Expand All @@ -9,6 +9,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsAPI = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
StatsModels = "3eaba693-59b7-5ba5-a881-562e759f1c8d"
Expand All @@ -19,9 +20,10 @@ Vcov = "ec2bfdc2-55df-4fc9-b9ae-4958c2cf2486"
DataFrames = "0.21, 0.22, 1.0"
FixedEffects = "2"
Reexport = "0.1, 0.2, 1.0"
StatsAPI = "1"
StatsBase = "0.33"
StatsFuns = "0.9, 1"
StatsModels = "0.6"
Tables = "1"
Vcov = "0.5"
Vcov = "0.6"
julia = "1.3"
56 changes: 29 additions & 27 deletions src/FixedEffectModel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ struct FixedEffectModel <: RegressionModel
contrasts::Dict

nobs::Int64 # Number of observations
dof_residual::Int64 # nobs - degrees of freedoms
df_FStat::Int64
dof::Int64 # Number parameters estimated - has_intercept
dof_residual::Int64 # nobs - degrees of freedoms
dof_tstat::Int64 # dof used for t-test and F-stat

rss::Float64 # Sum of squared residuals
tss::Float64 # Total sum of squares
Expand All @@ -49,30 +50,31 @@ has_iv(m::FixedEffectModel) = m.F_kp !== nothing
has_fe(m::FixedEffectModel) = has_fe(m.formula)


# Check API at https://github.com/JuliaStats/StatsBase.jl/blob/11a44398bdc16a00060bc6c2fb65522e4547f159/src/statmodels.jl
# fields
StatsBase.coef(m::FixedEffectModel) = m.coef
StatsBase.coefnames(m::FixedEffectModel) = m.coefnames
StatsBase.responsename(m::FixedEffectModel) = m.yname
StatsBase.vcov(m::FixedEffectModel) = m.vcov
StatsBase.nobs(m::FixedEffectModel) = m.nobs
StatsBase.dof_residual(m::FixedEffectModel) = m.dof_residual
StatsBase.r2(m::FixedEffectModel) = m.r2
StatsBase.adjr2(m::FixedEffectModel) = m.adjr2
StatsBase.islinear(m::FixedEffectModel) = true
StatsBase.deviance(m::FixedEffectModel) = m.tss
StatsBase.rss(m::FixedEffectModel) = m.rss
StatsBase.mss(m::FixedEffectModel) = deviance(m) - rss(m)


function StatsBase.confint(m::FixedEffectModel; level::Real = 0.95)
scale = tdistinvcdf(m.df_FStat, 1 - (1 - level) / 2)

StatsAPI.coef(m::FixedEffectModel) = m.coef
StatsAPI.coefnames(m::FixedEffectModel) = m.coefnames
StatsAPI.responsename(m::FixedEffectModel) = m.yname
StatsAPI.vcov(m::FixedEffectModel) = m.vcov
StatsAPI.nobs(m::FixedEffectModel) = m.nobs
StatsAPI.dof(m::FixedEffectModel) = m.dof
StatsAPI.dof_residual(m::FixedEffectModel) = m.dof_residual
Vcov.dof_tstat(m::FixedEffectModel) = m.dof_tstat
StatsAPI.r2(m::FixedEffectModel) = m.r2
StatsAPI.adjr2(m::FixedEffectModel) = m.adjr2
StatsAPI.islinear(m::FixedEffectModel) = true
StatsAPI.deviance(m::FixedEffectModel) = m.tss
StatsAPI.rss(m::FixedEffectModel) = m.rss
StatsAPI.mss(m::FixedEffectModel) = deviance(m) - rss(m)


function StatsAPI.confint(m::FixedEffectModel; level::Real = 0.95)
scale = tdistinvcdf(Vcov.dof_tstat(m), 1 - (1 - level) / 2)
se = stderror(m)
hcat(m.coef - scale * se, m.coef + scale * se)
end

# predict, residuals, modelresponse
function StatsBase.predict(m::FixedEffectModel, t)
function StatsAPI.predict(m::FixedEffectModel, t)
# Require DataFrame input as we are using leftjoin and select from DataFrames here
# Make sure fes are saved
if has_fe(m)
Expand All @@ -95,7 +97,7 @@ function StatsBase.predict(m::FixedEffectModel, t)
return out
end

function StatsBase.residuals(m::FixedEffectModel, t)
function StatsAPI.residuals(m::FixedEffectModel, t)
if has_fe(m)
m.residuals !== nothing || throw("To access residuals in a fixed effect regression, run `reg` with the option save = :residuals, and then access residuals with `residuals()`")
residuals(m)
Expand All @@ -115,7 +117,7 @@ function StatsBase.residuals(m::FixedEffectModel, t)
end


function StatsBase.residuals(m::FixedEffectModel)
function StatsAPI.residuals(m::FixedEffectModel)
has_fe(m) || throw("To access residuals, use residuals(x, t) where t is a Table")
m.residuals
end
Expand All @@ -140,7 +142,7 @@ function fe(m::FixedEffectModel; keepkeys = false)
end


function StatsBase.coeftable(m::FixedEffectModel; level = 0.95)
function StatsAPI.coeftable(m::FixedEffectModel; level = 0.95)
cc = coef(m)
se = stderror(m)
coefnms = coefnames(m)
Expand All @@ -155,7 +157,7 @@ function StatsBase.coeftable(m::FixedEffectModel; level = 0.95)
end
tt = cc ./ se
CoefTable(
hcat(cc, se, tt, fdistccdf.(Ref(1), Ref(m.df_FStat), abs2.(tt)), conf_int[:, 1:2]),
hcat(cc, se, tt, fdistccdf.(Ref(1), Ref(Vcov.dof_tstat(m)), abs2.(tt)), conf_int[:, 1:2]),
["Estimate","Std.Error","t value", "Pr(>|t|)", "Lower 95%", "Upper 95%" ],
["$(coefnms[i])" for i = 1:length(cc)], 4)
end
Expand Down Expand Up @@ -186,7 +188,7 @@ format_scientific(x) = @sprintf("%.3f", x)
function top(m::FixedEffectModel)
out = [
"Number of obs" sprint(show, nobs(m), context = :compact => true);
"Degrees of freedom" sprint(show, nobs(m) - dof_residual(m), context = :compact => true);
"Degrees of freedom" sprint(show, dof(m), context = :compact => true);
"R2" format_scientific(r2(m));
"R2 Adjusted" format_scientific(adjr2(m));
"F-Stat" sprint(show, m.F, context = :compact => true);
Expand Down Expand Up @@ -225,7 +227,7 @@ function Base.show(io::IO, m::FixedEffectModel)
coefnms = coefnms[newindex]
end
tt = cc ./ se
mat = hcat(cc, se, tt, fdistccdf.(Ref(1), Ref(m.df_FStat), abs2.(tt)), conf_int[:, 1:2])
mat = hcat(cc, se, tt, fdistccdf.(Ref(1), Ref(Vcov.dof_tstat(m)), abs2.(tt)), conf_int[:, 1:2])
nr, nc = size(mat)
colnms = ["Estimate","Std.Error","t value", "Pr(>|t|)", "Lower 95%", "Upper 95%"]
rownms = ["$(coefnms[i])" for i = 1:length(cc)]
Expand Down
3 changes: 2 additions & 1 deletion src/FixedEffectModels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ using LinearAlgebra
using Printf
using Reexport
using Statistics
using StatsAPI
using StatsBase
using StatsFuns
@reexport using StatsModels
Expand All @@ -37,4 +38,4 @@ has_iv,
has_fe,
Vcov

end
end
8 changes: 5 additions & 3 deletions src/fit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ function reg(
end
end
dof_residual_ = max(1, nobs - size(X, 2) - dof_fes - dof_add)
dof_ = max(1, size(X, 2) - (has_intercept | has_fe_intercept))


nclusters = nothing
if vcov isa Vcov.ClusterCovariance
Expand All @@ -388,8 +390,8 @@ function reg(

# Compute Fstat
F = Fstat(coef, matrix_vcov, has_intercept)
df_FStat_ = max(1, Vcov.df_FStat(vcov_data, vcov_method, has_intercept | has_fe_intercept))
p = fdistccdf(max(length(coef) - (has_intercept | has_fe_intercept), 1), df_FStat_, F)
dof_tstat_ = max(1, Vcov.dof_tstat(vcov_data, vcov_method, has_intercept | has_fe_intercept))
p = fdistccdf(dof_, dof_tstat_, F)
# Compute Fstat of First Stage
if has_iv && first_stage
Pip = Pi[(size(Pi, 1) - size(Z_res, 2) + 1):end, :]
Expand Down Expand Up @@ -449,5 +451,5 @@ function reg(
esample = trues(N)
end

return FixedEffectModel(coef, matrix_vcov, vcov, nclusters, esample, residuals2, augmentdf, fekeys, coef_names, response_name, formula_origin, formula_schema, contrasts, nobs, dof_residual_, df_FStat_, rss, tss_total, r2, adjr2, F, p, iterations, converged, r2_within, F_kp, p_kp)
return FixedEffectModel(coef, matrix_vcov, vcov, nclusters, esample, residuals2, augmentdf, fekeys, coef_names, response_name, formula_origin, formula_schema, contrasts, nobs, dof_, dof_residual_, dof_tstat_, rss, tss_total, r2, adjr2, F, p, iterations, converged, r2_within, F_kp, p_kp)
end

2 comments on commit 4887c70

@matthieugomez
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/63283

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.7.0 -m "<description of version>" 4887c7080410b43cc273f79fdc6ffc72c0de3629
git push origin v1.7.0

Please sign in to comment.