r-spatial / spatialreg

spatialreg: spatial models estimation and testing
https://r-spatial.github.io/spatialreg/
41 stars 12 forks source link

Fix SLX indirect impacts #26

Closed nk027 closed 1 year ago

nk027 commented 2 years ago

Hey,

So this PR closes issue #23 by scaling the coefficients of the linear model. I think this is ultimately the least invasive change for users, also see the commit message:

As documented in issue r-spatial#23 and doi.org/10.13140/RG.2.2.11269.68328 the average indirect effects of the SLX model are not correct for non-row-stochastic matrices. This commit fixes that.

To be maximally non-invasive to users, I apply the necessary scale factor to the coefficients of the underlying LM model. This means that the coefficients can be directly interpreted as partial effects -- which is probably the way it's being done anyways.

This could also be addressed in a more involved manner (for users and coders) -- we could apply the scale factor only to the indirect impacts (returned by 'impacts()') and only adjust the model used to compute total effects. I did not pursue this as it (1) would require more code, (2) be more contrived, and (3) does not reflect usage patterns that I would expect.

Also sorry for the messy changelog -- I should have separated actual changes from indentation adjustments better. The gist is this adjustment to the model:

# NK: Scale the impacts for proper average impacts if necessary (see #23)
if(listw$style != "W") { # For total impacts we need to apply this to the coefficents
      # Option A -- we scale the coefficients so they give average effects
      s_theta <- sum(vapply(listw$weights, sum, numeric(1L))) / n
      lm.model$coefficients[-seq(dvars[1])] <-
          lm.model$coefficients[-seq(dvars[1])] * s_theta
      # Option B -- we build a scale factor and apply that to indirect impacts + total ones
} # Row-stochastic has the proper scaling already
nk027 commented 2 years ago

Something to consider is how to handle this for SDM models -- it might also make sense to scale the coefficients there, but users should use the impacts() function for interpretation anyways.