# Change Base Level Categorical Vector in GLM

**URL:** <https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288>\
**Category:** General Usage\
**Tags:** glm\
**Created:** [December 4, 2018, 5:25pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288 "2018-12-04T17:25:44Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![matthieu](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@matthieu](https://discourse.julialang.org/u/matthieu)\
**Post date:** [December 4, 2018, 5:25pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/1 "2018-12-04T17:25:44Z")

</div>

Is there a way to change the base level of a categorical vector in GLM? It looks like the first level in the vector is chosen as the base level. I have tried to change the order of levels using `levels!` but it does not seem to make a difference

---

<div class="post-metadata">

**Author:** ![dmbates](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmbates/32/44_2.png) [@dmbates](https://discourse.julialang.org/u/dmbates)\
**Post date:** [December 4, 2018, 9:37pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/2 "2018-12-04T21:37:36Z")

</div>

Check out the use of `Contrasts` in the `StatModels` package, which is what generates the model matrix in a GLM model.

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [January 20, 2020, 11:45am UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/3 "2020-01-20T11:45:37Z")

</div>

Sorry for necroposting, I looked in the docs referred above but couldn’t find a simple example.

How do I specify that the base level in the following example should be `"none"` (because `m` comes before `n` and `s`, the base level is currently `"many"`)?

```julia
using DataFrames, GLM
df = DataFrame((x = x, y = y) for x in ("none", "some", "many") for y in rand(10))
ols = lm(@formula(y ~ x), df)

```

Thanks!

---

<div class="post-metadata">

**Author:** ![dmbates](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmbates/32/44_2.png) [@dmbates](https://discourse.julialang.org/u/dmbates)\
**Post date:** [January 20, 2020, 5:28pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/4 "2020-01-20T17:28:54Z")

</div>

If you convert the variable `x` to a `CategoricalArray` you can use `relevel!` to change the order of the levels.

---

<div class="post-metadata">

**Author:** ![DaymondLing](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/daymondling/32/8474_2.png) [@DaymondLing](https://discourse.julialang.org/u/DaymondLing)\
**Post date:** [January 20, 2020, 5:52pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/5 "2020-01-20T17:52:32Z")

</div>

The [StatsModels](https://juliastats.org/StatsModels.jl/stable/contrasts/) documentations says the default categorical encoding is DummyEncoding with the first level as the reference level. After constructing the untyped FormulaTerm and applying schema, you can create the ModelFrame and setcontrasts! to choose the contrast coding system and the base level you want:

```julia
mf = ModelFrame(@formula(y ~ 1 + a + b), df) # create ModelFrame

c1 = DummyCoding(base="a", levels=["a", "b", "c"]) # build desired contrasts
c2 = HelmertCoding(base=2, levels=[1, 2, 3])

setcontrast!(mf, Dict(:a => c1, :b => c2)) # set preferred contrast

```

@dmbates’s solution is easier if you don’t need to change contrast coding system.

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [January 23, 2020, 1:05pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/6 "2020-01-23T13:05:17Z")

</div>

I went with this, and just for posterity’s sake the function is `levels!` (not `relevel!`, though I agree it makes more sense).

---

<div class="post-metadata">

**Author:** ![dave.f.kleinschmidt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dave.f.kleinschmidt/32/55_2.png) [@dave.f.kleinschmidt](https://discourse.julialang.org/u/dave.f.kleinschmidt)\
**Post date:** [January 23, 2020, 2:53pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/7 "2020-01-23T14:53:46Z")

</div>

IIRC you can pass that dict as the `contrasts=` kw arg in the GLM functions…

Edit: you also don’t need to specify the levels just to change the base (they are extracted when creating the ContrastsMatrix later)

---

<div class="post-metadata">

**Author:** ![dave.f.kleinschmidt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dave.f.kleinschmidt/32/55_2.png) [@dave.f.kleinschmidt](https://discourse.julialang.org/u/dave.f.kleinschmidt)\
**Post date:** [January 23, 2020, 2:55pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/8 "2020-01-23T14:55:13Z")

</div>

The docs on this could probably be better to be fair 🙂

---

<div class="post-metadata">

**Author:** ![DaymondLing](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/daymondling/32/8474_2.png) [@DaymondLing](https://discourse.julialang.org/u/DaymondLing)\
**Post date:** [January 23, 2020, 3:06pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/9 "2020-01-23T15:06:16Z")

</div>

Yes, thank you. The flexibility of the GLM design allows one to define characteristics of categorical variables at several places.

---

<div class="post-metadata">

**Author:** ![dave.f.kleinschmidt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dave.f.kleinschmidt/32/55_2.png) [@dave.f.kleinschmidt](https://discourse.julialang.org/u/dave.f.kleinschmidt)\
**Post date:** [February 16, 2020, 10:34pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/10 "2020-02-16T22:34:17Z")

</div>

You should be able to do

```julia
ols = lm(@formula(y ~ x), df, contrasts = Dict(:x => DummyCoding(base="none")))

```

But that only works on GLM master at the moment (for some reason kwargs weren’t being passed to fit…). For now you can do

```julia
ols = fit(LinearModel, df, contrasts = Dict(:x => DummyCoding(base="none")))

```

Here’s an example to prove it works 😉

```julia
julia> df = DataFrame(y = rand(12), x = repeat(["some", "none", "many"], 4))
12×2 DataFrame
│ Row │ y │ x │
│ │ Float64 │ String │
├─────┼─────────────┼────────┤
│ 1 │ 0.886704 │ some │
│ 2 │ 0.226046 │ none │
│ 3 │ 0.196006 │ many │
│ 4 │ 0.40502 │ some │
│ 5 │ 0.000587951 │ none │
│ 6 │ 0.395679 │ many │
│ 7 │ 0.773263 │ some │
│ 8 │ 0.260962 │ none │
│ 9 │ 0.795655 │ many │
│ 10 │ 0.757367 │ some │
│ 11 │ 0.401757 │ none │
│ 12 │ 0.732157 │ many │

julia> fit(LinearModel, @formula(y ~ x), df, contrasts = Dict(:x => DummyCoding(base="none")))
StatsModels.TableRegressionModel{LinearModel{GLM.LmResp{Array{Float64,1}},GLM.DensePredChol{Float64,LinearAlgebra.Cholesky{Float64,Array{Float64,2}}}},Array{Float64,2}}

y ~ 1 + x

Coefficients:
───────────────────────────────────────────────────────────────────────────
             Estimate Std. Error t value Pr(>|t|) Lower 95% Upper 95%
───────────────────────────────────────────────────────────────────────────
(Intercept) 0.222338 0.112337 1.9792 0.0792 -0.0317865 0.476463
x: many 0.307536 0.158869 1.93578 0.0849 -0.0518506 0.666923
x: some 0.48325 0.158869 3.04182 0.0140 0.123864 0.842637
───────────────────────────────────────────────────────────────────────────

```

What’s happening internally here is that the contrasts argument gets passed to `schema` as a “hint” about how to code the `:x` variable:

```julia
julia> sch = schema(df, Dict(:x => DummyCoding(base="none")))
StatsModels.Schema with 2 entries:
  y => y
  x => x

julia> coefnames(sch[term(:x)])
2-element Array{String,1}:
 "x: many"
 "x: some"

julia> f = apply_schema(@formula(y ~ x), sch, RegressionModel)
FormulaTerm
Response:
  y(continuous)
Predictors:
  1
  x(DummyCoding:3→2)

julia> modelcols(f.rhs, df)
12×3 Array{Float64,2}:
 1.0 0.0 1.0
 1.0 0.0 0.0
 1.0 1.0 0.0
 1.0 0.0 1.0
 1.0 0.0 0.0
 1.0 1.0 0.0
 1.0 0.0 1.0
 1.0 0.0 0.0
 1.0 1.0 0.0
 1.0 0.0 1.0
 1.0 0.0 0.0
 1.0 1.0 0.0

julia> coefnames(f.rhs)
3-element Array{String,1}:
 "(Intercept)"
 "x: many"
 "x: some"

```

---

<div class="post-metadata">

**Author:** ![dave.f.kleinschmidt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dave.f.kleinschmidt/32/55_2.png) [@dave.f.kleinschmidt](https://discourse.julialang.org/u/dave.f.kleinschmidt)\
**Post date:** [February 17, 2020, 10:28am UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/11 "2020-02-17T10:28:22Z")

</div>

Update: once GLM v.1.3.7 is merged ([New version: GLM v1.3.7 by JuliaRegistrator · Pull Request #9611 · JuliaRegistries/General · GitHub](https://github.com/JuliaRegistries/General/pull/9611)) you should be able to use the `lm(::FormulaTerm, ::Table; contrasts=...)` syntax

---

<div class="post-metadata">

**Author:** ![DaymondLing](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/daymondling/32/8474_2.png) [@DaymondLing](https://discourse.julialang.org/u/DaymondLing)\
**Post date:** [February 17, 2020, 3:44pm UTC](https://discourse.julialang.org/t/change-base-level-categorical-vector-in-glm/18288/12 "2020-02-17T15:44:42Z")

</div>

Thank you! 😀
