Chi-Squared to Normal Distribution – How to Transform Chi-Squared to Normal Distribution

chi-squared-distributiondata transformationmathematical-statisticsnormal distributionprobability

The relationship between the standard normal and the chi-squared distributions is well known. I was wondering though, is there a transformation that can lead from a $\chi^2 (1)$
back to a standard normal distribution?

It can be easily seen that the square root transformation does not work as its range is only positive numbers. I believe the resulting distribution is called folded normal. Is there a clever trick that works here?

Best Answer

One option is to exploit the fact that for any continuous random variable $X$ then $F_X(X)$ is uniform (rectangular) on [0, 1]. Then a second transformation using an inverse CDF can produce a continuous random variable with the desired distribution - nothing special about chi squared to normal here. @Glen_b has more detail in his answer.

If you want to do something weird and wonderful, in between those two transformations you could apply a third transformation that maps uniform variables on [0, 1] to other uniform variables on [0, 1]. For example, $u \mapsto 1 - u$, or $u \mapsto u + k \mod 1$ for any $k \in \mathbb{R}$, or even $u \mapsto u + 0.5$ for $u \in [0, 0.5]$ and $u \mapsto 1 - u$ for $u \in (0.5, 1]$.

But if we want a monotone transformation from $X \sim \chi^2_1$ to $Y \sim \mathcal{N}(0,1)$ then we need their corresponding quantiles to be mapped to each other. The following graphs with shaded deciles illustrate the point; note that I have had to cut off the display of the $\chi^2_1$ density near zero.

Chi squared distribution with one degree of freedom and deciles shaded Standard normal distribution with deciles shaded

For the monotonically increasing transformation, that maps dark red to dark red and so on, you would use $Y = \Phi^{-1}(F_{\chi^2_1}(X))$. For the monotonically decreasing transformation, that maps dark red to dark blue and so on, you could use the mapping $u \mapsto 1-u$ before applying the inverse CDF, so $Y = \Phi^{-1}(1 - F_{\chi^2_1}(X))$. Here's what the relationship between $X$ and $Y$ for the increasing transformation looks like, which also gives a clue how bunched up the quantiles for the chi-squared distribution were on the far left!

Mapping from chi squared with 1 df to standard normal

If you want to salvage the square root transform on $X \sim \chi^2_1$, one option is to use a Rademacher random variable $W$. The Rademacher distribution is discrete, with $$\mathsf{P}(W = -1) = \mathsf{P}(W = 1) = \frac{1}{2}$$

It is essentially a Bernoulli with $p = \frac{1}{2}$ that has been transformed by stretching by a scale factor of two then subtracting one. Now $W\sqrt{X}$ is standard normal — effectively we are deciding at random whether to take the positive or negative root!

It's cheating a little since it is really a transformation of $(W, X)$ not $X$ alone. But I thought it worth mentioning since it seems in the spirit of the question, and a stream of Rademacher variables is easy enough to generate. Incidentally, $Z$ and $WZ$ would be another example of uncorrelated but dependent normal variables. Here's a graph showing where the deciles of the original $\chi^2_1$ get mapped to; remember that anything on the right side of zero is where $W = 1$ and the left side is $W = -1$. Note how values around zero are mapped from low values of $X$ and the tails (both left and right extremes) are mapped from the large values of $X$.

Mapping chi-squared to normal distribution

Code for plots (see also this Stack Overflow post):

require(ggplot2)
delta     <- 0.0001 #smaller for smoother curves but longer plot times
quantiles <- 10    #10 for deciles, 4 for quartiles, do play and have fun!

chisq.df <- data.frame(x = seq(from=0.01, to=5, by=delta)) #avoid near 0 due to spike in pdf
chisq.df$pdf <- dchisq(chisq.df$x, df=1)
chisq.df$qt <- cut(pchisq(chisq.df$x, df=1), breaks=quantiles, labels=F)
ggplot(chisq.df, aes(x=x, y=pdf)) +
  geom_area(aes(group=qt, fill=qt), color="black", size = 0.5) +
  scale_fill_gradient2(midpoint=median(unique(chisq.df$qt)), guide="none") +
  theme_bw() + xlab("x")

z.df     <- data.frame(x = seq(from=-3, to=3, by=delta))
z.df$pdf <- dnorm(z.df$x)
z.df$qt  <- cut(pnorm(z.df$x),breaks=quantiles,labels=F)
ggplot(z.df, aes(x=x,y=pdf)) +
  geom_area(aes(group=qt, fill=qt), color="black", size = 0.5) +
  scale_fill_gradient2(midpoint=median(unique(z.df$qt)), guide="none") +
  theme_bw() + xlab("y")

#y as function of x
data.df <- data.frame(x=c(seq(from=0, to=6, by=delta)))
data.df$y <- qnorm(pchisq(data.df$x, df=1))
ggplot(data.df, aes(x,y)) + theme_bw() + geom_line()

#because a chi-squared quartile maps to both left and right areas, take care with plotting order
z.df$qt2 <- cut(pchisq(z.df$x^2, df=1), breaks=quantiles, labels=F) 
z.df$w <- as.factor(ifelse(z.df$x >= 0, 1, -1))
ggplot(z.df, aes(x=x,y=pdf)) +
  geom_area(data=z.df[z.df$x > 0 | z.df$qt2 == 1,], aes(group=qt2, fill=qt2), color="black", size = 0.5) +
  geom_area(data=z.df[z.df$x <0 & z.df$qt2 > 1,], aes(group=qt2, fill=qt2), color="black", size = 0.5) +
  scale_fill_gradient2(midpoint=median(unique(z.df$qt)), guide="none") +
  theme_bw() + xlab("y")