# Empirical verification of the probability integral transform

I just discovered when working on Copulae that it was common knowledge that if $X$ is a continuous random variable with probability density function $F_{X}$, then $Y=F_{X}(x)$ follows a uniform distribution.

Before finding the proof online I was trying to empirically verify the above statement in R, but couldn't seem to succeed. Could someone please tell me what is wrong in my approach? In the code below I am plotting the histograms (empirical PDFs) of $10^3$ values sampled from the Normal CDF and of $10^3$ values sampled from the Cauchy CDF. Instead of observing uniform distributions, here is what I am getting:

par(mfrow=c(1,2))
hist(pnorm(ppoints(1e3)))
hist(pcauchy(ppoints(1e3)))


I was not expecting perfectly uniform distributions, but $10^3$ values should be enough to at least approach something that looks uniform. So what is wrong?

• What do you mean "sampled from the Normal and Cauchy CDFs. One set of points cannot be sampled from both. ppoints seems to be a built in function, but I don't really understand its documentation. – Matthew Drury Oct 15 '15 at 21:08
• It was clear from my code. But anyway, I edited my question for clarity. Thanks. – Antoine Oct 15 '15 at 21:09
• R has so many built in functions that it's often not clear to me what is a variable name that someone has assigned but not provided, and what is a built in I've never heard of. – Matthew Drury Oct 15 '15 at 21:12
• You're not generating random variables. See rnorm. – Scortchi - Reinstate Monica Oct 15 '15 at 21:16
• ppoints (roughly speaking) generates expected uniform quantiles, not normal (or whatever) random numbers – Glen_b Oct 15 '15 at 21:17

I believe your code just does not do what you want it to do. Here's what you want:

set.seed(154)
x <- rnorm(10000)
hist(pnorm(x))


This histogram looks uniform.

I believe

plot(ppoints(1000), pnorm(ppoints(1000)))


results in a plot of a portion of the graph of the normal cdf.

Here's a quick verification

plot((1:100 - 50)/25, pnorm((1:100 - 50)/25))
points(ppoints(25), pnorm(ppoints(25)), col="blue")


• +1 Yep, That's the way to do it. More generally p<thing>(r<thing>(n)) will be uniform for some distribution <thing> and sample size n. – Glen_b Oct 15 '15 at 21:18
• thanks. What misled me is that in the documentation for pnorm it is said that the argument $q$ that should be passed is a vector of quantiles. – Antoine Oct 15 '15 at 21:21
• @Glen_b That looks like C++ template. – Matthew Drury Oct 15 '15 at 21:23
• @Antoine the normal use case for pnorm is when you want to use it to get the probabilty associated with a quantile, but you're using it as a transformation. – Glen_b Oct 15 '15 at 21:33