Chris Butcher Chris Butcher - 4 months ago 18
Ruby Question

Generating a random number with weighted probability - 'Distribution' gem

I would like to create a random number generator, that generates a random decimal number:


  • Greater than 0.0

  • Less than 15.0

  • Where the probability of that number being close to 2.0 is relatively high

  • The probability of it being near 15.0 or very close to zero is very low



I'm terrifically poor at mathematics but my research seems to tell me I want to pull a random number from a Cumulative Distribution Function resembling a Fisher–Snedecor (F) pattern, a bit like this one:

http://cdn.app.compendium.com/uploads/user/458939f4-fe08-4dbc-b271-efca0f5a2682/742d7708-efd3-492c-abff-6044d78e3bbd/Image/6303a2314437d8fcf2f72d9a56b1293a/f_distribution_probability.png

I am using a Ruby gem called Distribution (https://github.com/sciruby/distribution) to try and achieve this. It looks like the right tool, but I'm having a terrible time trying to understand how to use it to achieve the desired outcome :( Any help please.

Answer

I'll take it back, there is no rng call for F. So, if you want to use Distribution gem, what I would propose is to use Chi2 with 4 degrees of freedom.

Mode for Chi2 with k degress of freedom is equal to k-2, so for 4 d.f. you'll get mode at 2, see here. My Ruby is rusty, bear with me

require 'distribution'
normal = Distribution::Normal.rng(0)

g1 = normal.call
g2 = normal.call
g3 = normal.call
g4 = normal.call

chi2 = g1*g1 + g2*g2 + g3*g3 + g4*g4

UPDATE

You have to truncate it at 15, so if generated chi2 is greater than 15 just reject it and generate another one. Though I would say you won't see a lot of value above 15, check graphs for PDF/CDF.

UPDATE II

And if you want to get samples from F, make generic Chi2 generator for d degrees of freedom from code above, and just sample ratio of chi2, check here

chi2_d1 = DChi2(d1)
chi2_d2 = DChi2(d2)

f = (chi2_d1.call / d1) / (chi2_d2.call / d2)

UPDATE III

And, frankly, I don't see how you could get F distribution working for you. It is ok at 0, but mode is equal to (d1-2)/d1 * d2/(d2 + 2), and it is hard to see it equal to 2. Graph you provided has mode at about 1/3.

Comments