Hello,
I'm fitting a zero-inflated beta regression, and as such need to specify a different likelihood structure for zero and non-zero observations. Currently, I have structured the likelihood section like so:
#Phi (only varies with year not observation)
for(y in 1:nYrs){ log(phi[y]) <- a[3] + u[y, 3] }
for(n in 1:N){
#Zi
yz[n] ~ dbern(zi[n])
logit(zi[n]) <- a[1] + u[yr_n[n], 1] + inprod(bzi[1:Kzi], X[n, 1:Kzi])
if(yz[n] == 0){
#Observed value (non-zero)
y[n] ~ dbeta(shape[1, n], shape[2, n])
shape[1, n] <- mu[n] * phi[yr_n[n]]
shape[2, n] <- (1 - mu[n]) * phi[yr_n[n]]
#Mu
logit(mu[n]) <- a[2] + u[yr_n[n], 2] + inprod(bmu[1:Kmu], Z[n, 1:Kmu])
}
}
Here, yz is a dummy binary variable indicating whether (1) or not (0) each observation (y) is equal to zero, and is provided as a vector in the model constants. However, when I try to compile the model, I get the error I'd expect when tring to apply an if statement to an estimated parameter:
Condition must be able to be evaluated based on values in 'constants'
I presume this is because part of the condition is not included in the constants (i.e., the index, n). Is there a way to make this work, I feel like there should be?
One option I've thought of is to create another vector including the index of all non-zero observations, to which I can compare n, which in R would be:
if(n %in% non_zeros){...}
But obviously there is no %in% operator in NIMBLE - is there a NIMBLE alternative to %in%?
Of course, I think the recommended solution is probably to create a nimbleFunction. I've had a go at this:
zibr_likelihood <- nimbleFunction(
run = function(y = double(0), yz = double(0), u = double(1), phi = double(0),
s = double(0), X = double(1), Z = double(1)) {
if(!yz){
#Zi
yz ~ dbern(zi)
logit(zi) <- a[1] + u[1] + inprod(bzi, X)
#Observed value (non-zero)
y ~ dbeta(shape[1], shape[2])
shape[1] <- mu * phi
shape[2] <- (1 - mu) * phi
#Mu
logit(mu) <- a[2] + u[2] + inprod(bmu, Z) + s
} else {
#Zi
yz ~ dbern(zi)
logit(zi) <- a[1] + u[1] + inprod(bzi, X)
}
})
However, I think due to the fact some of the parameters of my model are only included in the likelihood (i.e., the section in the function) I get an error when compiling:
Defining model
[Note] 'yz' is provided in 'constants' but not used in the model code and is being ignored.
Error in processBUGScode(recurseCode, nextContextID, lineNumber = lineNumber, :
Error: zibr_likelihood not allowed in BUGS code in zibr_likelihood(y = y[n], yz = y[n], u = u[yr_n[n], ], phi = phi[yr_n[n]], s = s[yr_n[n], loc_n[n]], X = X[n, 1:Kzi], Z = Z[n, 1:Kmu])
Ideally I'd like to write the likelihood directly within the nimbleModel (i.e., not use a nimbleFunction), although this is purely for aesthetic reasons so I'm perfectly happy for someone to point out the errors in my function.
Thanks very much for any help,
Ciar