Hi all!
So, I’m experimenting with the linear regression ecosystem (GLM
, Plots
, DataFrames
, StatsPlots
and CSV
). I understood how to produce a simple linear regression model and a multivariate one.
I know that OLS works even when your function is not linear in the variables, provided it is in the parameters. For instance, I tried fitting this paraboloid:
# excerpt to generate it
f((x,y)) = (x, y, x^2 + 2 * y^2 + 10*randn())
# excerpt to fit it
fm = @formula(z ~ x^2 + y^2)
and it works! Yay!
However, now I’m trying shifting the vertex:
f((x,y)) = (x, y, (x - x_0)^2 + 2 * (y - y_0)^2 + 10*randn())
Of course, now the estimate is off. How can I tell Julia that there are two more parameters to fit?
I’ve tried this
fm = @formula(z ~ (x - x_0)^2 + (y - y_0)^2)
but it panics when I try to fit it:
julia> fm = @formula(z ~ (x - x_0)^2 + (y - y_0)^2)
FormulaTerm
Response:
z(unknown)
Predictors:
(x,x_0)->(x - x_0) ^ 2
(y,y_0)->(y - y_0) ^ 2
julia> @time(model = lm(fm, df))
ERROR: ArgumentError: There isn't a variable called 'x_0' in your data; the nearest names appear to be: x
Stacktrace:
[1] ModelFrame(f::FormulaTerm{Term, Tuple{FunctionTerm{typeof(^), var"#87#91", (:x, :x_0)}, FunctionTerm{typeof(^), var"#89#93", (:y, :y_0)}}}, data::NamedTuple{(:x, :y, :z), Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}}}; model::Type{LinearModel}, contrasts::Dict{Symbol, Any})
@ StatsModels ~/.julia/packages/StatsModels/6uCgU/src/modelframe.jl:76
[2] fit(::Type{LinearModel}, f::FormulaTerm{Term, Tuple{FunctionTerm{typeof(^), var"#87#91", (:x, :x_0)}, FunctionTerm{typeof(^), var"#89#93", (:y, :y_0)}}}, data::DataFrame, args::Nothing; contrasts::Dict{Symbol, Any}, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ StatsModels ~/.julia/packages/StatsModels/6uCgU/src/statsmodel.jl:85
[3] fit
@ ~/.julia/packages/StatsModels/6uCgU/src/statsmodel.jl:78 [inlined]
[4] #lm#5
@ ~/.julia/packages/GLM/P0Ris/src/lm.jl:184 [inlined]
[5] lm (repeats 2 times)
@ ~/.julia/packages/GLM/P0Ris/src/lm.jl:184 [inlined]
[6] top-level scope
@ ./timing.jl:262 [inlined]
[7] top-level scope
@ ./REPL[287]:0
Is there a way to do it?
Thanks!