Skip to content

Commit 40b8777

Browse files
committed
Add dof_aov, dof_aovres, formula_aov
1 parent 7e40f64 commit 40b8777

File tree

9 files changed

+62
-42
lines changed

9 files changed

+62
-42
lines changed

docs/src/Algorithm_AnovaFixedEffectModels.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ The mean residual deviance $\sigma^2$
4646
```math
4747
\sigma^2 =\frac{D_n}{df_r}
4848
```
49-
where $D_n$ is the residual sum of squares of $M_n$; $df_r$ is the degrees of freedom of the residuals, i.e. $df_r = s - n(\mathcal{C})$, where $s$ is number of samples.
49+
where $D_n$ is the residual sum of squares of $M_n$; $df_r$ is the degrees of freedom of the residuals, i.e. $df_r = nob - n(\mathcal{C})$, where $nob$ is number of observations.
5050

5151
## F-test
5252
F-value is a vector

docs/src/Algorithm_AnovaGLM.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ For ordinary linear regression,
5353
```math
5454
\sigma^2 =\frac{D_n}{df_r}
5555
```
56-
where $D_n$ is the residual sum of squares of $M_n$; $df_r$ is the degrees of freedom of the residuals, i.e. $df_r = s - n(\mathcal{C})$, where $s$ is number of samples.
56+
where $D_n$ is the residual sum of squares of $M_n$; $df_r$ is the degrees of freedom of the residuals, i.e. $df_r = nob - n(\mathcal{C})$, where $nob$ is number of observations.
5757

5858
## F-test
5959
F-value is a vector

docs/src/AnovaBase.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ AnovaBase.canonicalgoodnessoffit
4444
AnovaBase.ftest_nested
4545
AnovaBase.lrt_nested
4646
AnovaBase.dof_residual(aov::AnovaResult)
47+
AnovaBase.dof_aovres(::RegressionModel)
48+
AnovaBase.dof_aov(::RegressionModel)
49+
AnovaBase.formula_aov(::RegressionModel)
4750
AnovaBase.predictors(::RegressionModel)
4851
AnovaBase.anovatable(::AnovaResult{<: FullModel})
4952
```

docs/src/Interface.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ It is recommended that `anova` additionally dispatched on wrapper types and the
2323
## [predictors](./AnovaBase.md#AnovaBase.predictors-Tuple{RegressionModel})
2424
This function returns a tuple of terms which can be used in ANOVA (some terms may not be used because of ANOVA type or model itself).
2525

26-
There is a default method for `RegressionModel`, i.e., `formula(model).rhs.terms`. If the formula for `SomeModel` has special structure like `MixedModel`, this function should be overloaded.
26+
There is a default method for `RegressionModel`, i.e., `formula_aov(model).rhs.terms`. If the formula for `SomeModel` has special structure like `MixedModel`, this function or [`formula_aov`](./AnovaBase.md#AnovaBase.formula_aov-Tuple{RegressionModel}) should be overloaded.
2727

2828
## AnovaModels
2929
### [NestedModels](./AnovaBase.md#AnovaBase.NestedModels)
@@ -62,4 +62,7 @@ This function is not essential for ANOVA; it is just for convenience to create n
6262
`AnovaBase` provides a lot of functions to work on formula, terms and contrasts. See [Developer utility](./AnovaBase.md#Developer-utility)
6363

6464
## Other function
65-
* [`dof_residual`](./AnovaBase.md#StatsAPI.dof_residual-Tuple{AnovaResult}) applies `dof_residual` to all models by default. If `dof_residual(::SomeModel)` is not valid for ANOVA, customize `dof_residual(::AnovaResult{<: AnovaModel{SomeModel}})` alternatively.
65+
* [`dof_aovres`](./AnovaBase.md#AnovaBase.dof_aovres-Tuple{RegressionModel}) calls `dof_residual` by default. If `dof_residual(::SomeModel)` is not valid for ANOVA, customize `dof_aovres(::SomeModel)`. This function is utilized in the following function [`dof_residual`].
66+
* [`dof_residual`](./AnovaBase.md#StatsAPI.dof_residual-Tuple{AnovaResult}) applies [`dof_aovres`](./AnovaBase.md#AnovaBase.dof_aovres-Tuple{RegressionModel}) to all models by default. This function is utilized in the [`anovatable`](./AnovaBase.md#AnovaBase.anovatable-Tuple{AnovaResult{<:FullModel}}).
67+
* [`dof_aov`](./AnovaBase.md#AnovaBase.dof_aov-Tuple{RegressionModel}) calls `dof` by default. If `dof(::SomeModel)` is not valid for ANOVA, customize `dof_aov(::SomeModel)`. Currently, no other function depends on this function.
68+
* [`formula_aov`](./AnovaBase.md#AnovaBase.formula_aov-Tuple{RegressionModel}) calls `formula` by default. If `formula(::SomeModel)` is not valid for ANOVA, customize `formula_aov(::SomeModel)`. Several functions including [`predictors`](./AnovaBase.md#AnovaBase.predictors-Tuple{RegressionModel}), and `show` function for ANOVA depend on this function.

src/fit.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ end
5050

5151
# Calculate dof from assign
5252
"""
53-
dof_asgn(v::Vector{Int})
53+
dof_asgn(assign::Vector{Int})
5454
55-
Calculate degrees of freedom of each predictors. 'assign' can be obtained by `StatsModels.asgn(f::FormulaTerm)`. For a given `trm::RegressionModel`, it is as same as `trm.mm.assign`.
55+
Calculate degrees of freedom of each predictors. `assign` can be obtained by `StatsModels.asgn(f::FormulaTerm)`. For a given `trm::RegressionModel`, it is as same as `trm.mm.assign`.
5656
5757
The index of the output matches values in the orinal `assign`. If any index value is not in `assign`, the default is 0.
5858
@@ -80,8 +80,6 @@ function dof_asgn(v::Vector{Int})
8080
dofv
8181
end
8282

83-
@deprecate dof(v::Vector{Int}) dof_asgn(v::Vector{Int})
84-
8583
const FixDispDist = Union{Bernoulli, Binomial, Poisson}
8684
"""
8785
canonicalgoodnessoffit(::FixDispDist) = LRT

src/interface.jl

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,47 @@ end
4646
4747
Degrees of freedom of residuals.
4848
49-
By default, it applies `dof_residual` to models in `aov.anovamodel`.
49+
By default, it applies `dof_aovres` to models in `aov.anovamodel`.
5050
"""
51-
dof_residual(aov::AnovaResult{M, T, N}) where {M, T, N} = ntuple(x -> dof_residual(aov.anovamodel.model), N)
52-
dof_residual(aov::AnovaResult{<: MultiAovModels}) = map(dof_residual, aov.anovamodel.model)
51+
dof_residual(aov::AnovaResult{M, T, N}) where {M, T, N} = ntuple(x -> dof_aovres(aov.anovamodel.model), N)
52+
dof_residual(aov::AnovaResult{<: MultiAovModels}) = map(dof_aovres, aov.anovamodel.model)
53+
54+
"""
55+
dof_aovres(m::RegressionModel)
56+
57+
Degrees of freedom of residuals for ANOVA.
58+
59+
By default, it calls `dof_residual`.
60+
"""
61+
dof_aovres(m::RegressionModel) = dof_residual(m)
62+
63+
"""
64+
dof_aov(m::RegressionModel)
65+
66+
Degrees of freedom of model for ANOVA.
67+
68+
By default, it calls `dof`.
69+
"""
70+
dof_aov(m::RegressionModel) = dof(m)
71+
72+
"""
73+
formula_aov(m::RegressionModel)
74+
75+
Formula of model for ANOVA.
76+
77+
By default, it calls `formula`.
78+
"""
79+
formula_aov(m::RegressionModel) = formula(m)
5380

5481
"""
5582
predictors(model::RegressionModel)
5683
predictors(anovamodel::FullModel)
5784
5885
Return a tuple of `Terms` which are predictors of the model or anovamodel.
5986
60-
By default, it returns `formula(model).rhs.terms`; if the formula has special structures, this function should be overloaded.
87+
By default, it returns `formula_aov(model).rhs.terms`; if the formula has special structures, this function should be overloaded.
6188
"""
62-
predictors(model::RegressionModel) = formula(model).rhs.terms
89+
predictors(model::RegressionModel) = formula_aov(model).rhs.terms
6390
predictors(anovamodel::FullModel) = getindex.(Ref(predictors(anovamodel.model)), anovamodel.pred_id)
6491

6592
"""

src/io.jl

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ testname(::Type{FTest}) = "F test"
1010
testname(::Type{LRT}) = "Likelihood-ratio test"
1111
#testname(M::AnovaStatsRao) = "Rao score test"
1212
#testname(M::AnovaStatsCp) = "Mallow's Cp"
13-
@deprecate tname testname
14-
1513
"""
1614
prednames(aov::AnovaResult)
1715
prednames(anovamodel::FullModel)
@@ -30,17 +28,14 @@ function prednames(anovamodel::MultiAovModels)
3028
end
3129
prednames(model::RegressionModel) = vectorize(prednames(predictors(model)))
3230

33-
@deprecate coefnames(aov::AnovaResult) prednames(aov::AnovaResult)
34-
@deprecate coefnames(x, ::Val{:anova}) prednames(x)
35-
3631
function show(io::IO, anovamodel::FullModel)
3732
println(io, "FullModel for type $(anovamodel.type) test")
3833
println(io)
3934
println(io, "Predictors:")
4035
println(io, join(prednames(anovamodel), ", "))
4136
println(io)
4237
println(io, "Formula:")
43-
println(io, formula(anovamodel.model))
38+
println(io, formula_aov(anovamodel.model))
4439
println(io)
4540
println(io, "Coefficients:")
4641
show(io, coeftable(anovamodel.model))
@@ -51,7 +46,7 @@ function show(io::IO, anovamodel::NestedModels{M, N}) where {M, N}
5146
println(io)
5247
println(io, "Formulas:")
5348
for(id, m) in enumerate(anovamodel.model)
54-
println(io, "Model $id: ", formula(m))
49+
println(io, "Model $id: ", formula_aov(m))
5550
end
5651
println(io)
5752
println(io, "Coefficients:")
@@ -66,7 +61,7 @@ function show(io::IO, anovamodel::MixedAovModels{M, N}) where {M, N}
6661
println(io)
6762
println(io, "Formulas:")
6863
for(id, m) in enumerate(anovamodel.model)
69-
println(io, "Model $id: ", formula(m))
64+
println(io, "Model $id: ", formula_aov(m))
7065
end
7166
println(io)
7267
println(io, "Coefficients:")
@@ -83,7 +78,7 @@ function show(io::IO, aov::AnovaResult{<: FullModel, T}) where {T <: GoodnessOfF
8378
println(io)
8479
println(io, "Type $(anova_type(aov)) test / $(testname(T))")
8580
println(io)
86-
println(io, formula(aov.anovamodel.model))
81+
println(io, formula_aov(aov.anovamodel.model))
8782
println(io)
8883
println(io, "Table:")
8984
show(io, at)
@@ -96,7 +91,7 @@ function show(io::IO, aov::AnovaResult{<: MultiAovModels, T}) where {T <: Goodne
9691
println(io, "Type $(anova_type(aov)) test / $(testname(T))")
9792
println(io)
9893
for(id, m) in enumerate(aov.anovamodel.model)
99-
println(io, "Model $id: ", formula(m))
94+
println(io, "Model $id: ", formula_aov(m))
10095
end
10196
println(io)
10297
println(io, "Table:")

src/term.jl

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
# Function related to terms
2-
@deprecate has_intercept hasintercept
3-
42
"""
53
any_not_aliased_with_1(terms)
64
@@ -98,8 +96,7 @@ getterms(term::FunctionTerm) = [term.exorig]
9896

9997
# Determine selected terms for type 2 ss
10098
"""
101-
isinteract(m::MatrixTerm, id1::Int, id2::Int)
102-
isinteract(f::TupleTerm, id1::Int, id2::Int)
99+
isinteract(f::Union{MatrixTerm, TupleTerm}, id1::Int, id2::Int)
103100
104101
Determine if `f[id2]` is an interaction term of `f[id1]` and other terms.
105102
@@ -133,14 +130,10 @@ isinteract(f::MatrixTerm, id1::Int, id2::Int) = isinteract(f.terms, id1, id2)
133130
isinteract(f::TupleTerm, id1::Int, id2::Int) = issubset(getterms(f[id1]), getterms(f[id2]))
134131

135132
const doc_select_interaction = """
136-
select_super_interaction(m::MatrixTerm, id::Int)
137-
select_super_interaction(f::TupleTerm, id::Int)
138-
select_sub_interaction(m::MatrixTerm, id::Int)
139-
select_sub_interaction(f::TupleTerm, id::Int)
140-
select_not_super_interaction(m::MatrixTerm, id::Int)
141-
select_not_super_interaction(f::TupleTerm, id::Int)
142-
select_not_sub_interaction(m::MatrixTerm, id::Int)
143-
select_not_sub_interaction(f::TupleTerm, id::Int)
133+
select_super_interaction(f::Union{MatrixTerm, TupleTerm}, id::Int)
134+
select_sub_interaction(f::Union{MatrixTerm, TupleTerm}, id::Int)
135+
select_not_super_interaction(f::Union{MatrixTerm, TupleTerm}, id::Int)
136+
select_not_sub_interaction(f::Union{MatrixTerm, TupleTerm}, id::Int)
144137
145138
Return a set of index of `f`, which
146139
@@ -220,8 +213,6 @@ function select_not_sub_interaction(f::TupleTerm, id::Int)
220213
s
221214
end
222215

223-
@deprecate selectcoef(f::MatrixTerm, id::Int) select_super_interaction(f, id)
224-
225216
# Create sub-formula
226217
"""
227218
subformula(f::FormulaTerm, id; kwargs...)
@@ -331,8 +322,6 @@ function clear_schema(t::MatrixTerm)
331322
length(ts) 1 ? ts[1] : ts
332323
end
333324

334-
@deprecate clearschema clear_schema
335-
336325
# reschema only happen when using TupleTerm rather than MatrixTerm
337326
reschema_formula(lhs::AbstractTerm, ts::TupleTerm, reschema::Bool) =
338327
reschema ? FormulaTerm(clear_schema(lhs), clear_schema.(ts)) : FormulaTerm(lhs, collect_matrix_terms(ts))

test/runtests.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using AnovaBase
2-
import AnovaBase: dof_residual, nobs, anovatable, prednames, predictors, coeftable, dof_asgn, canonicalgoodnessoffit
2+
import AnovaBase: dof_residual, dof_aovres, formula_aov, dof_aov, dof, nobs, anovatable, prednames, predictors, coeftable, dof_asgn, canonicalgoodnessoffit
33
using Distributions: Gamma, Binomial
44
import Base: show
55
using Test
@@ -28,11 +28,12 @@ macro test_error(x)
2828
end
2929
end
3030

31+
dof(x::Int) = x
3132
dof_residual(x::Int) = x
3233
nobs(x) = ntuple(one, length(x))
3334
nobs(x::Int) = one(x)
3435
predictors(::Int) = tuple(Term.(Symbol.(["x$i" for i in 1:7]))...)
35-
predictors(model::StatsModels.TableRegressionModel{Int64, Matrix{Float64}}) = formula(model).rhs
36+
predictors(model::StatsModels.TableRegressionModel{Int64, Matrix{Float64}}) = formula_aov(model).rhs
3637
coeftable(model::StatsModels.TableRegressionModel{Int64, Matrix{Float64}}) = []
3738
anovatable(::AnovaResult{<: FullModel{StatsModels.TableRegressionModel{Int64, Matrix{Float64}}}, LikelihoodRatioTest, 7}; rownames = string.(1:7)) =
3839
AnovaBase.AnovaTable([
@@ -168,9 +169,13 @@ anovatable(::AnovaResult{<: FullModel{StatsModels.TableRegressionModel{Int64, Ma
168169
ntuple(one float, 3),
169170
ntuple(zero float, 3),
170171
NamedTuple())
171-
@testset "attr.jl" begin
172+
@testset "attr.jl and interface.jl" begin
172173
@test nobs(ft) == 1
173174
@test nobs(lrt) == 1
175+
@test dof_aov(ft.anovamodel.model[1]) == 1
176+
@test dof_aov(lrt.anovamodel.model) == 1
177+
@test formula_aov(ft.anovamodel.model[1]) == formula(ft.anovamodel.model[1])
178+
@test formula_aov(lrt.anovamodel.model) == formula(lrt.anovamodel.model)
174179
@test dof_residual(lrt) == (1, 1, 1, 1, 1, 1, 1)
175180
@test dof_residual(lrt2) == (1, 1, 1)
176181
@test deviance(ft) == ft.deviance

0 commit comments

Comments
 (0)