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)

1 Like

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.

1 Like

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!