Reputation: 41
I have a random variable X with pdf f(x)=4xe^-x
, where x>0
.
How do i draw a random sample of size, let's say, 1000 from this distribution?
Upvotes: 0
Views: 1598
Reputation: 16910
One easy solution is rejection sampling (though see my comments on Severin Pappadeux's answer below). A general rejection sampling algorithm is pretty easy to implement in R (and I would be surprised if it were not implemented in several packages, I just didn't look up which packages would have such functionality):
#' Rejection sampling
#'
#' @param f A function calculating the density of interest
#' @param g A function giving the proposal density
#' @param rg A function providing random samples from g
#' @param M A numeric vector of length one giving a bound on the the ratio
#' f(x) / g(x). M must be > 1 and greater than or equal to f(x) / g(x) over
#' the whole support of X.
#' @param n An integer vector of length one giving the number of samples to
#' draw; the default is ten thousand.
#' @param ... Further arguments to be passed to g and rg
rejection_sampling <- function(f, g, rg, M, n = 10000, ...) {
result <- numeric(n)
for ( i in 1:n ) {
reject <- TRUE
while ( reject ) {
y <- rg(n = 1, ...)
u <- runif(1)
if ( u < ( f(y) / (M * g(y, ...)) ) ) {
result[i] <- y
reject <- FALSE
}
}
}
return(result)
}
Then we can use that to get a sample from your distribution, and plot the sample's density along with the true probability density to see how well it worked:
x <- seq(0.01, 15, 0.01)
f <- function(x) 4 * x * exp(-x)
y <- f(x)
set.seed(123)
z <- rejection_sampling(f = f, g = dexp, rg = rexp, M = 10, n = 1e3, rate = 1/4)
dens <- density(z, from = 0.01, to = 15)
scaling_constant <- max(y) / max(dens$y)
plot(x, y, type = "l", xlab = "x", ylab = "f(x)", lty = 2, col = "blue")
lines(dens$x, dens$y * scaling_constant, col = "red", lty = 3)
legend("topright", bty = "n", lty = 2:3, col = c("blue", "red"),
legend = c("True f(x)", "(Re-scaled) density of sample"))
Rejection sampling works by taking samples from a proposal distribution and rejecting them if a random uniform deviate is greater than the ratio f(x) / M g(x)
, where g(x)
is your proposal density, and M
is a bound on f(x) / g(x)
as briefly described in the Roxygen documentation above.
I used above an exponential proposal distribution with a rate parameter of 1/4. You could use others.
This p.d.f. is proportional to a Gamma distribution with a shape of 2 and scale of 1, as mentioned by Severin Pappadeux's answer. (That is, if you plug those parameters into the Gamma p.d.f., you'll see it differs from yours only by a scaling constant). Depending on what you're doing this for, that could be a better way to go, or this way. I'm not sure if your objective is to generate samples from arbitrary distributions such as this one as an example, or you need samples from this distribution itself, etc.... Usually it's best to recognize if your arbitrary p.d.f. is actually an example of an implemented distribution, but if you're not in that situation, you need something like rejection sampling.
Upvotes: 3
Reputation: 20080
This is Gamma distribution with shape=a=2 and scale=1.
q <- rgamma(1000, shape = 2, scale = 1)
Upvotes: 4