I have a list of keys in a dictionary, and I would like to assign a number between 0 and 1 to each item in such a way that the assigned numbers sum to 1. How would one do this? I tried something with rand(), but that didn't work. Any suggestions?
CodePudding user response:
You can generate a "probability vector", i.e. a vector of length d
whose entries are all non-negative and sum to 1, uniformly at random by:
using Random
rand_probvec(d) = rand_probvec(Random.GLOBAL_RNG, d)
function rand_probvec(rng, d)
unif = rand(rng, d - 1)
T = eltype(unif)
w = zeros(T, d 1)
w[2:d] .= sort(unif)
w[d 1] = one(T)
return diff(w)
end
following http://www.cs.cmu.edu/~nasmith/papers/smith tromble.tr04.pdf.
If you don't care if your distribution is drawn uniformly at random, you could just draw d
random numbers and divide by their sum, e.g.
function rand_probvec2(d)
v = rand(d)
return v / sum(v)
end
Either way, once you can generate random probability vectors, if you have a list of elements you wish to assign the probabilities to, you can do something like
my_list = ["a", "b", "c"]
prob_vec = rand_probvec(length(my_list))
my_dist = Dict(k => prob_vec[i] for (i, k) in enumerate(my_list))
CodePudding user response:
The more mathematical answer is to use a Dirichlet distribution. Specifically, a symmetric Dirichlet with concentration parameter 1.0 is uniform on the N-simplex:
julia> using Distributions
julia> d = rand(Dirichlet(4, 1.0))
4-element Vector{Float64}:
0.1629111431248381
0.025227624238719375
0.030334086399317672
0.7815271462371249
julia> sum(d)
1.0