JuliaInterop / JuliaCall

Embed Julia in R
https://non-contradiction.github.io/JuliaCall/index.html
Other
267 stars 36 forks source link

Calling Julia package functions in R formulas #156

Open alansz opened 3 years ago

alansz commented 3 years ago

I am using Julia 1.5.3's MixedModels 3.1.4 package to fit linear mixed models. It offers a function MixedModels.zerocorr that is using in Julia formulas like this:

fit(MixedModel,@formula(value ~ zerocorr(1+round|subprog)), df)

I can fit models a model like this in JuliaCall (0.17.2) like this:

j<-julia_setup() j$library('MixedModels') j$assign('df',df) j$eval('m1=fit(MixedModel @formula(value ~ zerocorr(1+round|subprog)), df)')

But I can not find a way to build up the formula as a string in R and pass it in When I try to use the zerocorr syntax that's part of MixedModels but not valid in R, I get:

j$assign('frm',as.formula('value ~ zerocorr(1+round|subprog)')) Error: Error happens in Julia. UndefVarError: zerocorr not defined

Same result with j$assign('frm',as.formula('value ~ MixedModels.zerocorr(1+round|subprog)'))

Ok, fair enough, julia_assign is doing some kind of evaluation of the formula in its type-conversion and doesn't know what to do with zerocorr().

So I have also tried:

j$assign('frms','value ~ zerocorr(1+round|subprog)') j$eval('m1=fit(MixedModel, @formula(frms) ,df)') Error: Error happens in Julia. LoadError: type Symbol has no field head

What am I missing? Is there a best way to have Juliacall tell Julia to convert a string to a julia formula?

Non-Contradiction commented 3 years ago

Thanks for the feedback! The issue seems to be relevant to RCall.jl, which is a dependency for JuliaCall, and I open an issue there.

Non-Contradiction commented 3 years ago

Before we figure out JuliaInterop/RCall.jl#402, there can be some workaround for the problem. For example, after j$library('MixedModels'), the following two workarounds can be used

Workaround 1

julia_command("function formula1(expr) @eval @formula($expr) end") ## only needs to run once
jformula <- julia_call("formula1", str2lang("value ~ zerocorr(1+round|subprog)"), need_return = "J")
julia_assign("frm", jformula)

Workaround 2

julia_command("import RCall.rcopy")
julia_command("function rcopy(::Type{RCall.StatsModels.FormulaTerm}, l::Ptr{LangSxp})
    expr = rcopy(Expr, l)
    @eval RCall.StatsModels.@formula($expr)
end")
## the code above only needs to run once, then things like following should work without further workaround
julia_assign("frm", as.formula("value ~ zerocorr(1+round|subprog)"))

The two workarounds are to mimic https://github.com/JuliaInterop/RCall.jl/blob/52a97c561f98e5a8274da3c610af86bc75b1e41c/src/convert/formula.jl#L39-L42 as pointed out in JuliaInterop/RCall.jl#402.

alansz commented 3 years ago

Thank you foe these workarounds!

On Jan 10, 2021, at 8:44 AM, Changcheng Li notifications@github.com wrote:

 Before we figure out JuliaInterop/RCall.jl#402, there can be some workaround for the problem. For example,

Workaround 1

julia_command("function formula1(expr) @eval @formula($expr) end") ## only needs to run once jformula <- julia_call("formula1", str2lang("value ~ zerocorr(1+round|subprog)"), need_return = "J") julia_assign("frm", jformula) Workaround 2

julia_command("import RCall.rcopy") julia_command("function rcopy(::Type{RCall.StatsModels.FormulaTerm}, l::Ptr{LangSxp}) expr = rcopy(Expr, l) @eval RCall.StatsModels.@formula($expr) end")

the code above only needs to run once, then things like following should work without further workaround

julia_assign("frm", as.formula("value ~ zerocorr(1+round|subprog)")) The two workarounds are to mimic https://github.com/JuliaInterop/RCall.jl/blob/52a97c561f98e5a8274da3c610af86bc75b1e41c/src/convert/formula.jl#L39-L42 as pointed out in JuliaInterop/RCall.jl#402.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.