Reputation: 125
I have:
mu_x - a 10x10 matrix of real values
ptype - a 10000 long vector
sender_name_type - a 10000 long vector
I'd like to find the values of
x_real - a 10000 long vector
The code I currently have, and works, is:
for(i in 1:N){
if(x_available[i]){
x_real[i]~normal(x[i],0.01);} else{
x_real[i]~normal(mu_x[ptype[i],sender_name_type[i]],0.1);
}
}
I'd like however, to vectorize it. To do that, I'd first need to deal with the if clause. To do that, I tried just adding two distributions, like so:
x_real ~ normal(mu_x[ptype,sender_name_type],0.1) * (1-x_avaiable) + normal(x,0.01) * x_available;
However, Rstan seems to not handle adding/multiplying distributions. The second approach I tried was like so:
x_real ~ normal(mu_x[ptype,sender_name_type],0.1);
x_real[x_available == 1] ~ normal(x,0.01);
Which is similar to the first approach, but it redefines the rows of x_real, for which the condition is met. However, it gives me the error of
No matches for:
real[] ~ normal(matrix, real)
How can I vectorize my current solution, if possible? Are there any other ways I could speed it up?
Upvotes: 2
Views: 942
Reputation: 4990
The Stan language does not flatten when you use multiple indices like [ptype,sender_name_type]
. Nor does the Stan language support indexing by logical condition, such as [x_available == 1]
.
The way to do something like this is loop to set up the arguments, and then evaluate the likelihood in one step to avoid unnecessary memory allocations. In your case, it would look like
vector[N] x_hat;
vector[N] noise;
for (i in 1:N) {
x_hat[i] = x_available[i] ? x[i] : mu_x[ptype[i],sender_name_type[i]];
noise[i] = x_available[i] ? 0.01 : 0.1;
}
target += normal_lpdf(x_real | x_hat, noise);
Upvotes: 2