-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Joint modeling of point and areal data #125
Comments
Automated support for Basic ips <- ipoints(samplers=polygons, domain=mesh, group="polygonID") Then we need a way to apply this to the predictor. A <- inla.spde.make.A(
mesh,
coordinates(ips),
block=ips$polygonID,
block.rescale = "none",
weights = ips$weight) Then the like(formula = response ~ log(A %*% exp(here + goes + your + predictor + expression)),
model = "poisson",
data = ips,
allow_combine = TRUE) Any non-spatial covariates would need to be added to I'm sure there are more details to work out depending on your model details, but the principle is given above. Apart from internal as yet unpublished projects we haven't really shown how to do There's also a snag with the construction above, as I'm almost certain it doesn't allow you to specify the response variable, as it has different length than data = c(list(response = data$response), as.list(as.data.frame(ips))) and use explicit This should become a bit easier to deal with once I add a separate response variable argument to |
Additional note: the proper count model aggregation is only well-defined for Poisson, as Po(lambda1)+Po(lambda2)~Po(lambda1+lambda2). For other models, including Binomial with different probabilities, this doesn't hold, so there's no longer a strong theoretical argument saying |
I expect to wrap the basic version of this into a |
Thanks for the quick and detailed response. I'm working with Gaussian observations rather than a count model aggregation. ips <- ipoints(samplers=polygons, domain=mesh, group="polygonID")
A <- inla.spde.make.A(
mesh,
coordinates(ips),
block=ips$polygonID,
block.rescale = "sum")
like(formula = response ~ A %*% (my + predictor + expression),
model = "gaussian",
data = ips,
allow_combine = TRUE) I then define a second like(formula = response ~ my + predictor + expression + field(pt_coordinates, model=matern),
model = "gaussian",
data = pts) and combine them with |
Yes, for Gaussian observations it's also fine! comp <- ~ Intercept1(1) + Intercept2(1) +
covariate(eval_covar(cbind(easting, northing)), model = "linear") +
field(pt_coordinates, model=matern),
like1 <-
like(formula = response1 ~ A %*% (Intercept1 + covariate),
family = "gaussian",
data = c(list(response1 = data$response1), as.list(as.data.frame(ips))),
allow_combine = TRUE)
like2 <-
like(formula = response2 ~ .,
include = c("Intercept2", "field")
family = "gaussian",
data = pts)
bru(comp, like1, like2) For this to work, the coordinate names in |
In testing a simple example, I can't seem to get around a differing number of rows error when trying to index the spde object for the polygons: For reference, In my existing INLA code, I'm doing something like this, with different A matrices for points and polys: s.index <- inla.spde.make.index(name="spatial.field", n.spde=spde$n.spde)
# data and poly_data are data.frames
stack.pts <- inla.stack(
data=list(response = data$response),
A=list(A.pts,1),
effects=list(c(s.index, list(Intercept=1)),
list(covar = data$covar)))
stack.poly <- inla.stack(
data=list(response = poly_data$response),
A=list(A.poly,1),
effects=list(c(s.index, list(Intercept=1)),
list(covar = poly_data$covar)))
formula ~ Intercept + f(spatial.field, model=spde) The A matrix you've suggested for the aggregation is identical to the one I'm already using, so I'm not sure where the issue is arising. Manually running comp <- ~ Intercept1(1) + field(spatial.field, model=spde)
like1 <-
like(formula = response ~ A %*% (Intercept1 + field),
family = "gaussian",
data = c(list(response = data$response), s.index),
allow_combine = TRUE)
fit <- bru(comp, like1) |
Aha, I see the problem; I mixed two different approaches.
In your Gaussian/linear case, you can either change the A matrix to handle it correctly, or set the field component mapper to bru_mapper_index(matern$n.spde).
The downside of the latter approach is that it affects both likelihoods, so the other one would then also need an A matrix. Correcting the A mtatrix is therefore a generally better method here, I think.
In the nonlinear case (Poisson) the correct solution is to change the A matrix. Instead of inla.spde.make.A it should actually be a much simpler matrix, where each row contains the integration point weight values corresponding to each “block”.
I think this should do it:
A = sparseMatrix(i=ips$polygonid, j=seq_len(NROW(ips)),x=ips$weight, dims=c(max(ips$polygonid), NROW(ips)))
Finn
… On 17 Nov 2021, at 18:15, Bradley Wilson ***@***.***> wrote:
In testing a simple example, I can't seem to get around a differing number of rows error when trying to index the spde object for the polygons:
Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, : arguments imply differing number of rows: 14271, 17369
For reference, In my existing INLA code, I'm doing something like this, with different A matrices for points and polys:
s.index <- inla.spde.make.index(name="spatial.field", n.spde=spde$n.spde)
# data and poly_data are data.frames
stack.pts <- inla.stack(
data=list(response = data$response),
A=list(A.pts,1),
effects=list(c(s.index, list(Intercept=1)),
list(covar = data$covar)))
stack.poly <- inla.stack(
data=list(response = poly_data$response),
A=list(A.poly,1),
effects=list(c(s.index, list(Intercept=1)),
list(covar = poly_data$covar)))
formula ~ Intercept + f(spatial.field, model=spde)
The A matrix you've suggested for the aggregation is identical to the one I'm already using, so I'm not sure where the issue is arising. Manually running A %*% spatial.field runs just fine. Do I need a custom mapper to access the spde object with a list of indices rather than coordinate pairs?
comp <- ~ Intercept1(1) + field(spatial.field, model=spde)
like1 <-
like(formula = response ~ A %*% (Intercept1 + field),
family = "gaussian",
data = c(list(response = data$response), s.index),
allow_combine = TRUE)
fit <- bru(comp, like1)
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
|
No luck. Still getting the same error (using both approaches), just with different numbers of rows. |
Can you send a reproducible example I can check/debug? |
The corrected A matrix can also be constructed via INLA::inla.spde.make.block.A(inla.as.dgTMatrix(Diagonal(NROW(ips), ips$weight)),block=ips$polygonid,rescale=...) that allows choosing and optional scaling method ("none" for plain integration or "sum" for spatial averaging). |
Sure, this shows the same error on the gorillas data. polygons <- gorillas$plotsample$plots
polygons@data <- tibble::rownames_to_column(polygons@data) # add group
mesh <- gorillas$mesh
spde <- inla.spde2.matern(mesh=mesh)
ips <- ipoints(samplers=polygons, domain=mesh, group="rowname")
# ipoints drops the grouping variable, adding back in
ips@data <- cbind(ips@data, polygonid = floor(as.numeric(tibble::rownames_to_column(ips@data)$rowname)))
A <- inla.spde.make.block.A(Diagonal(nrow(ips), ips$weight), block=ips$polygonid, rescale="sum")
comp <- ~ Intercept1(1) + field(cbind(x,y), model = spde)
data$response <- rnorm(nrow(polygons), sd = 0.4)
like1 <-
like(formula = response ~ A %*% (Intercept1 + field),
family = "gaussian",
data = c(list(response = data$response), as.list(as.data.frame(ips))),
allow_combine = TRUE)
fit <- bru(comp, like1) |
I'm not sure precisely what error message you get, and for what part of the code. library(INLA)
#> Loading required package: Matrix
#> Loading required package: foreach
#> Loading required package: parallel
#> Loading required package: sp
#> This is INLA_21.11.16 built 2021-11-16 14:00:50 UTC.
#> - See www.r-inla.org/contact-us for how to get help.
#> - To enable PARDISO sparse library; see inla.pardiso()
library(inlabru)
data("gorillas", package="inlabru")
polygons <- gorillas$plotsample$plots
polygons@data <- tibble::rownames_to_column(polygons@data) # add group
mesh <- gorillas$mesh
spde <- inla.spde2.matern(mesh=mesh)
ips <- ipoints(samplers=polygons, domain=mesh, group="rowname")
#> Warning in showSRID(SRS_string, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=longlat +R=1
#> +no_defs +type=crs
#> Warning in showSRID(SRS_string, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
#> Warning in showSRID(SRS_string, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=longlat
#> +R=6378137 +no_defs +type=crs
#> Warning in showSRID(SRS_string, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
#> Warning in showSRID(SRS_string, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=longlat
#> +R=6378137 +no_defs +type=crs
#> Warning in showSRID(SRS_string, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
#> Warning in showSRID(SRS_string, format = "PROJ", multiline = "NO", prefer_proj
#> = prefer_proj): Discarded ellps unknown in Proj4 definition: +proj=geocent +R=1
#> +units=m +no_defs +type=crs
#> Warning in showSRID(SRS_string, format = "PROJ", multiline = "NO", prefer_proj =
#> prefer_proj): Discarded datum unknown in Proj4 definition
# The rowname column is still there. Convert to numeric.
# head(ips)
# coordinates rowname weight
# 1 (581.9648, 674.5587) 1 0.0006067968
ips@data$polygonid <- as.numeric(ips@data$rowname)
A <- inla.spde.make.block.A(
inla.as.dgTMatrix(Diagonal(nrow(ips), ips$weight)),
block=ips$polygonid,
rescale="sum")
comp <- ~ Intercept1(1) + field(cbind(x,y), model = spde)
data <- data.frame(response = rnorm(nrow(polygons), sd = 0.4))
like1 <-
like(formula = response ~ as.vector(A %*% (Intercept1 + field)),
family = "gaussian",
data = c(list(response = data$response), as.list(as.data.frame(ips))),
allow_combine = TRUE)
fit <- bru(comp, like1) Created on 2021-11-17 by the reprex package (v2.0.1) |
The |
This is getting closer to having full support in the package. In particular, there are mappers that can be used in the predictor expression for the aggregations. For examples in the unit tests, see https://github.com/inlabru-org/inlabru/blob/devel/tests/testthat/test-aggregate.R |
@bradleyswilson did you figure out how to do this in the end? I'm new to inlabru but trying something similar with two point datasets and one areal gridded dataset and keep hitting blocks... |
@nickschurch I believe I went back to using INLA syntax instead of inlabru for this particular instance, although I haven't tested the updates Finn has made since then. My issue was mostly computational, which I solved another way with mesh projections in a custom tiling scheme. |
@bradleyswilson I have just scanned through this but I believe this is now supported in the bru mapper system with the logsumexp mapper. We have included an example in the software paper that we are currently drafting (very nearly finished!). I can't share the data here but here is a sneak peek at the code: # Define Matern/SPDE model
matern <- inla.spde2.pcmatern(
mesh,
prior.range = c(2, 0.1),
prior.sigma = c(3, 0.1)
)
# Define the intermediate zone integration scheme
ips <- fm_int(mesh, samplers = glasgow_iz)
agg <- bru_mapper_logsumexp(
rescale = FALSE,
n_block = nrow(glasgow_iz)
)
# Define model components and formula
cmp <- ~ 0 + beta(1) + xi(main = geometry, model = matern)
fml <- count ~ ibm_eval(
agg,
input = list(weights = weight, block = .block),
state = beta + xi
)
# Construct the likelihood
lik <- like(
formula = fml,
family = "poisson",
data = ips,
response_data = glasgow_iz
)
# Fit the model
fit <- bru(
components = cmp,
lik
) Here |
Greetings, I've been working with INLA for joint modeling of point and areal data (similar to the model in this paper).
I'm looking to transferring the model over to inlabru to help handle large numbers of predictions, but am struggling to figure out how I'd implement the model specification.
Is the preferred approach to use the like() and bru() functionality to specify two likelihoods, one for the point data and another for the polygons? When I pass spatial polygons directly to a field(polygons, model = matern), I get an a
cannot coerce class ‘structure("Polygons", package = "sp")’ to a data.frame
error. I'm looking for it to be constructed similar to the inla.spde.make.block.A from the normal INLA package.The text was updated successfully, but these errors were encountered: