I'd like to sample from "zipf" distribution from a bounded domain.
That is, assume that the domain is {1,...,N}, I'd like each element in the domain, i, to be chosen with probability proportional to i ** -a
, where a
is a parameter of the distribution.
numpy
provides a zipf sampler (numpy.random.zipf), but it does not allow me to restrict the domain.
How can I easily sample from such distribution?
If the distribution parameter, a
, is larger than 1, I can use the numpy
sampler by rejecting (and re-sampling) all samples larger than N
. However, since it does not restrict the sample range, trying to use any smaller values of a
does not work.
When the domain is finite, there shouldn't be a problem to use such a
s, and that is what I need for my application.
Using scipy.stats
, you could create a custom discrete distribution:
bounded_zipf = stats.rv_discrete(name='bounded_zipf', values=(x, weights))
For example,
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
N = 7
x = np.arange(1, N+1)
a = 1.1
weights = x ** (-a)
weights /= weights.sum()
bounded_zipf = stats.rv_discrete(name='bounded_zipf', values=(x, weights))
sample = bounded_zipf.rvs(size=10000)
plt.hist(sample, bins=np.arange(1, N+2))
plt.show()
yields
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With