How can I generate sample from a distribution with probability mass $P(X=x)$ in R? I know that probability mass, but it is not from a known distribution, also it is not linear, instead it has a complicated form. Can I use the inverse cdf method on the density, by working out the cdf and inverting it $X=F^{-1}(U)$?
2 Answers
Yes, you can use the inverse CDF method. Let $x_1, x_2, \dots$ be the (possibly infinite) sequence of elements which have positive probability masses $p_1,p_2,\dots>0$. Let $I\in \mathbb{N}$ have distribution $\mathbb{P}(I=i)=p_i.$ Generate a uniform random variable $U$ and then let $J$ be such that $$\mathbb{P}(I<J)=F_I(J) \le U < F_I(J+1).$$ Take $X=x_J$. Then $$\mathbb{P}(X=x_j)=\mathbb{P}(F_I(j)\le U < F_I(j+1))=F_I(j+1)-F_I(j)=p_j.$$
While it's possible to use methods based on the inverse-cdf if you don't know anything more than the probability mass function, but in many cases it can be terribly inefficient especially if it's unbounded. [If all you have is the pmf you can build a table of the cdf for say the bottom 99.9% of the distribution, for example, which will work but you still have to search it in some fashion -- e.g. binary search starting at the median might make sense, and you still have to do something else to deal with the tail beyond your table.]
There are a number of alternative approaches but which one might work best for your problem depends on the problem and how much you'll need to sample from it (e.g. if you need to sample 10000 values from it only once, you may not need a very efficient method -- what does it matter if it takes two minutes to run if you only need it one time? ... but if you need to sample billions of times, or many people need to use this thing, then it would be worth investing the effort to make it very efficient).
There are many approaches that work directly with the pmf, including a number of table methods and accept-reject methods that might be suitable for your problem. There are several techniques described in my answer in How to sample from a discrete distribution but there's not enough information in your question to make concrete suggestions (such as whether one of those methods or some other might suit you better) -- it's hard to give explicit advice in the absence of details.
-
$\begingroup$ I added some detail on accept-reject (rejection method) at the linked post $\endgroup$– Glen_bCommented Apr 19, 2017 at 4:02
sample
function. With the argumentreplace=TRUE
this simulates from the specified pmf using the alias method, see related thread $\endgroup$