How to implement R-like marginaleffects?

Hi,

I’m interested in how to implement calculation of partial derivatives/marginal effects similar to the package marginaleffects in r.

I translated some code from the excellent documentation, to simply calculate the marginal effect of hp for every unit in the dataset.

using GLM, RDatasets, DataFrames

mtcars = dataset("datasets", "mtcars")
rename!(mtcars, lowercase.(names(mtcars)))
lm_mod = glm(@formula(mpg ~ hp * cyl), mtcars, Normal())

partial_derivative = function(data, model, eps)
    d1 = transform(data, :hp => (x -> x .- eps / 2) => :hp)
    d2 = transform(data, :hp => (x -> x .+ eps / 2) => :hp)
    (p1, p2) = map(d -> predict(model, d), [d1, d2])
    round.((p2-p1)/eps, digits=2)
end

partial_derivative(mtcars, lm_mod, 1e-4)

What would be a reasonable way to implemented this in a way that could give me unit-level marginaleffects for every variable in the model efficiently?
I have been looking at ForwardDiff, but haven’t been able to figure out how to do it.

Note this is crossposted on zulip.

Check out GitHub - beacon-biosignals/Effects.jl: Effects Prediction for Regression Models

Thank you!

I’m looking to understand how to implement this in a better (faster/cleaner) way.
I was looking at the implementation in Effects earlier, but didn’t quite get how it was done.
How can I implement something similar to my example above in a way that scales with more variables/data?

I’m the main author of Effects.jl, so if I knew how to make things faster/cleaner, I would have already done it. This is the core computation:

_difference_method! is factored out into a separate function so that it can use gradients from ForwardDiff or analytic gradients for common link functions via package extensions.

2 Likes

Thanks! I’ll take a closer look at this.