Generating a vector of random values from Truncated normal distribution between 0.05 and 0.50

Hello All,

I am trying to generate 10 random variables that must come from normal(0.10,1) T[0.05,0.50].

I know that T[lower, upper] cannot be used in ‘generated quantities’ part of Stan program.

This link https://mc-stan.org/docs/2_27/stan-users-guide/truncated-random-number-generation.html

provides on how to generate the random variables from a truncated normal distribution using a function.

I have tried doing this, but when I try to generate a vector of draws ( say N = 10) , my numbers are all same ( give below). I have specified a sigma of 1, so there should be noise in the data.

I am very new at this function part of Stan so may be I am doing some thing wrong?

Here is my code:


functions {
real normal_lub_rng(real mu, real sigma, real lb, real ub) {
real p_lb = normal_cdf(lb, mu, sigma);
real p_ub = normal_cdf(ub, mu, sigma);
real u = uniform_rng(p_lb, p_ub);
real y = mu + sigma * Phi(u);
return y;
}
}

data {
int<lower=0> N; // Number of obs
}

generated quantities {
real v[N];

for (i in 1:N)
v[i] = normal_lub_rng(0, 1,0.05,0.50);

}


OUTPUT

Inference for Stan model: anon_model_319f1d93b88035fb32272af48e582c2a.
4 chains, each with iter=100; warmup=0; thin=1;
post-warmup draws per chain=100, total post-warmup draws=400.

    mean se_mean     sd   2.5%  97.5%  n_eff   Rhat

v[1] 0.81 8.9e-4 0.02 0.79 0.84 384 0.99
v[2] 0.81 8.4e-4 0.02 0.79 0.84 392 1.0
v[3] 0.81 9.2e-4 0.02 0.79 0.84 340 1.01
v[4] 0.81 8.5e-4 0.02 0.79 0.84 397 1.0
v[5] 0.81 9.6e-4 0.02 0.79 0.84 328 1.0
v[6] 0.81 9.4e-4 0.02 0.79 0.84 347 1.0
v[7] 0.82 8.4e-4 0.02 0.79 0.84 434 1.0
v[8] 0.81 9.1e-4 0.02 0.79 0.84 373 1.01
v[9] 0.81 9.2e-4 0.02 0.79 0.84 336 1.0
v[10] 0.81 8.3e-4 0.02 0.79 0.84 416 0.99

Could anyone please assist me with this.

Thank you very much

Antony

you need inv_Phi(u) not Phi(u)

Thanks spinkney, it was a typo.

I have changed it now, but my draws still don’t change much, eventhough I have given a sigma of 20.

Do you know the reason, I am struggling here !

functions {
real normal_lub_rng(real mu, real sigma, real lb, real ub) {
real p_lb = normal_cdf(lb, mu, sigma);
real p_ub = normal_cdf(ub, mu, sigma);
real u = uniform_rng(p_lb, p_ub);
real y = mu + sigma * inv_Phi(u);
return y;
}
}

data {
int<lower=0> N; // Number of obs
}

generated quantities {
real v[N];

for (i in 1:N)
v[i] = normal_lub_rng(0, 20,0.05,0.50);

}

Inference for Stan model: anon_model_6da495d26f8b014647729cfc340428a2.
4 chains, each with iter=100; warmup=0; thin=1;
post-warmup draws per chain=100, total post-warmup draws=400.

    mean se_mean     sd   2.5%  97.5%  n_eff   Rhat

v[1] 0.27 6.3e-3 0.13 0.06 0.49 419 1.0
v[2] 0.28 6.6e-3 0.13 0.07 0.49 417 1.0
v[3] 0.28 6.2e-3 0.13 0.06 0.49 418 1.0
v[4] 0.27 6.8e-3 0.13 0.06 0.49 365 1.0
v[5] 0.27 6.4e-3 0.13 0.06 0.49 392 1.0
v[6] 0.27 6.5e-3 0.13 0.06 0.48 409 1.0
v[7] 0.28 5.8e-3 0.13 0.07 0.49 476 1.0
v[8] 0.27 6.2e-3 0.13 0.06 0.49 431 1.0
v[9] 0.27 5.9e-3 0.13 0.06 0.49 471 1.0
v[10] 0.27 6.2e-3 0.13 0.06 0.49 435 1.0

Can you please help?

Yes, the summary is taking the average of all the draws. I don’t know why it’s above 0.5, did you have different bounds?

Anyway, you need to inspect the draws rather than the average. Those will vary within the bounds.

The summary output is actually not easiy readible all the draws looks like they are between 0.06 - 0.49. so that is okay.

I see it now I was taking the mean of random draws.

Thanks for the pointer, I get it now.

Much appreciated!