I would like to look at the size of the expected false positive and false negative rates in employment hiring decisions. Let's assume that it is useful to dichotomize job performance after hiring.

The hiring decisions are based on a predictor with a linear (Pearson) correlation of r with a criterion.

I am able to approach this using Monte Carlo methods, assuming a bivariate normal distribution, and for applicant populations of various assumed levels of competence and various selection ratios.

But perhaps there is an analytic approach that would be much easier.

I seek formulas for the expected false positive and false negative rates based on r.

Alternatively, perhaps there are published tables for this.

  • 1
    $\begingroup$ Joel, can you clarify a bit further what is missing from Stephan Kolassa's answer. There is no analytical formula to compute these rates (at least not for bivariate normal distribution of the predicted and actual performance). Stephan explains the mathematical structure and shows an example to compute/approximate it numerically (not by Monte Carlo method but by integrating). So what is missing? $\endgroup$ Oct 9 '20 at 9:48

Let's assume that it is useful to dichotomize job performance after hiring.

That is a strong assumption. But let's go with it.

Let $X$ denote the predictor and $Y$ the actual performance. Let's further assume that the bivariate normal distribution describing $(X,Y)$ has marginal variances of $1$. Then your correlation turns into the covariance, and life is a little easier. Working with different (co)variances will likely not change a lot, just make the formulas messier. Thus,

$$ (X,Y)\sim N(0,\Sigma)\quad\text{with}\quad \Sigma=\begin{pmatrix}1 & r \\ r & 1\end{pmatrix}. $$


$$ \det\Sigma=1-r^2\quad\text{and}\quad\Sigma^{-1}=\frac{1}{1-r^2} \begin{pmatrix}1 & -r \\ -r & 1\end{pmatrix}, $$

we can write down the density:

$$f(x,y) = \frac{1}{2\pi\sqrt{1-r^2}}e^{-\frac{1}{2}(x\;y)\Sigma^{-1}\begin{pmatrix}x \\ y\end{pmatrix}}. $$

We use some cutoffs $c$ (for the predictor; anyone scoring $X>c$ is predicted to perform well) and $d$ (for the true value; anyone scoring $Y>d$ actually does perform well). Here is some random data for $r=0.5$, $c=0.5$ and $d=0.8$:


The top left grey rectangle shows false negatives (FN), the top right white rectangle shows true positives (TP), the bottom left white rectangle gives true negatives (TN), and the bottom right grey rectagle gives false positive (FP). Calculating the incidences of all these is just a question of evaluating the integral over the density with appropriate integral limits:

$$ \begin{align*} FN(c,d,r) =& \int_{-\infty}^c\int_d^\infty f(x,y)\,dy\,dx \\ TP(c,d,r) =& \int_c^\infty\int_d^\infty f(x,y)\,dy\,dx \\ TN(c,d,r) =& \int_{-\infty}^c\int_{-\infty}^d f(x,y)\,dy\,dx \\ FP(c,d,r) =& \int_c^\infty\int_{-\infty}^d f(x,y)\,dy\,dx \end{align*} $$

Finally, to get the false positive/false negative rates, plug these into the formulas:

$$ FPR=\frac{FP}{FP+TN}\quad\text{and}\quad FNR=\frac{FN}{FN+TP}. $$

R code for that little plot:

rr <- 0.5
nn <- 500
cutoff_pred <- 0.5
cutoff_true <- 0.8

obs <- rmvnorm(nn,sigma=cbind(c(1,rr),c(rr,1)))


Now, these integrals need to be approximated, or looked up in tables. Specifically, let's use $F_r$ to denote the bivariate CDF, and $G$ to denote the univariate CDF of the marginal $N(0,1)$ distribution. Then

$$ \begin{align*} FN(c,d,r) =& \int_{-\infty}^c\int_d^\infty f(x,y)\,dy\,dx = G(c)-F_r(c,d)\\ TP(c,d,r) =& \int_c^\infty\int_d^\infty f(x,y)\,dy\,dx = 1-FN-TN-FP\\ TN(c,d,r) =& \int_{-\infty}^c\int_{-\infty}^d f(x,y)\,dy\,dx = F_r(c,d) \\ FP(c,d,r) =& \int_c^\infty\int_{-\infty}^d f(x,y)\,dy\,dx = G(d)-F_r(c,d) \end{align*} $$

In R, we can use the bivariate package for the bivariate CDFs. For instance, with the cutoffs $c$ and $d$ and the correlation $r$ as per above, the calculations seem to work out compared to $10^7$ simulations:

> nn <- 1e7
> set.seed(1)
> obs <- rmvnorm(nn,sigma=cbind(c(1,rr),c(rr,1)))
> library(bivariate)
> F <- nbvcdf (mean.X=0, mean.Y=0, sd.X=1, sd.Y=1, cor=rr)
> # false negatives:
> (FN <- pnorm(cutoff_pred)-F(cutoff_pred,cutoff_true))
[1] 0.08903922
> sum(obs[,1]<cutoff_pred & obs[,2]>cutoff_true)/nn
[1] 0.0889579
> # true negatives:
> (TN <- F(cutoff_pred,cutoff_true))
[1] 0.6024232
> sum(obs[,1]<cutoff_pred & obs[,2]<cutoff_true)/nn
[1] 0.6024315
> # false positives:
> (FP <- pnorm(cutoff_true)-F(cutoff_pred,cutoff_true))
[1] 0.1857214
> sum(obs[,1]>cutoff_pred & obs[,2]<cutoff_true)/nn
[1] 0.1857027
> # true positives:
> (TP <- 1-FN-TN-FP)
[1] 0.1228162
> sum(obs[,1]>cutoff_pred & obs[,2]>cutoff_true)/nn
[1] 0.1229079

Thus, our results would here be

> (FPR <- FP/(FP+TN))
[1] 0.2356438
> (FNR <- FN/(FN+TP))
[1] 0.420283

Finally, the bivariate package offers quite a number of other bivariate distributions, so you could experiment a bit. The vignette may be helpful here.

Edit: we can collect the calculations above in a little R function:

calculate_FPR_and_FNR <- function ( rr, cutoff_pred, cutoff_true ) {
    F <- nbvcdf (mean.X=0, mean.Y=0, sd.X=1, sd.Y=1, cor=rr)
    # false negatives:
    FN <- pnorm(cutoff_pred)-F(cutoff_pred,cutoff_true)
    # true negatives:
    TN <- F(cutoff_pred,cutoff_true)
    # false positives:
    FP <- pnorm(cutoff_true)-F(cutoff_pred,cutoff_true)
    # true positives:
    TP <- 1-FN-TN-FP

So if we want to get the FPR and FNR for $r=0.3$ and $c=d=1.65$, we would invoke this function as follows:

#        FPR        FNR 
# 0.04466637 0.85820503

To create and fill a whole table, we first decide on which values of $r$, $c$ and $d$ are relevant to us, then collect all combinations using expand.grid() and finally apply our function. The result table has 23,275 rows, and running the script below takes a few seconds - if you want a finer grid, or a larger range of $c$ and $d$, then it will of course have even more rows and take longer.

rr <- seq(-0.9,0.9,by=0.1)
cutoff_pred <- seq(-1.7,1.7,by=0.1)
cutoff_true <- seq(-1.7,1.7,by=0.1)
result <- data.frame(expand.grid(rr=rr,cutoff_pred=cutoff_pred,cutoff_true=cutoff_true),FPR=NA,FNR=NA)
for ( ii in 1:nrow(result) ) {
    result[ii,4:5] <- calculate_FPR_and_FNR(rr=result[ii,1],

#     rr cutoff_pred cutoff_true       FPR        FNR
# 1 -0.9        -1.7        -1.7 1.0000000 0.04664418
# 2 -0.8        -1.7        -1.7 1.0000000 0.04664418
# 3 -0.7        -1.7        -1.7 0.9999911 0.04664377
# 4 -0.6        -1.7        -1.7 0.9998502 0.04663720
# 5 -0.5        -1.7        -1.7 0.9991204 0.04660316
# 6 -0.4        -1.7        -1.7 0.9969898 0.04650377

Finally, export the table, e.g., to a CSV file, using write.table().

  • $\begingroup$ You give definitional formulas, which is nice, but they are impossible to use to compute the false positive and false negative numbers and rates. (That is why you evaluate these formulas using R.) I am looking for analytic solutions to these formulas, not a Monte Carlo approach. Perhaps tables exist with solutions to these formulas or actual analytic solutions for approximating the solutions, if not exact solutions. That is what I asked for in my original posting. $\endgroup$
    – Joel W.
    Oct 8 '20 at 14:25
  • $\begingroup$ I do not think there are tables for bivariate normal distributions, and certainly no analytic solutions (just as there is no closed form solution for the normal CDF). But the formulas above will allow you to create tables for any combination of $c, d, r$ that is realistic. You should then be able to map the more general case of general marginal variances to these tables. $\endgroup$ Oct 8 '20 at 14:41
  • $\begingroup$ By "create tables for any combination of 𝑐,𝑑,𝑟 that is realistic" do you mean running a simulation as in the R code you (so kindly) provided? $\endgroup$
    – Joel W.
    Oct 8 '20 at 15:14
  • $\begingroup$ I wouldn't call it a "simulation", unless you do so with a random sample from the bivariate normals. After all, we get deterministic results for given values of $c,d,r$. Just decide which combinations of these parameters are relevant to your application, calculate the FPRs and FNRs based on the formulas above, and store them in a table. $\endgroup$ Oct 8 '20 at 15:37
  • 1
    $\begingroup$ I edited the answer to include the calculation for your specific example, and code for filling a table. Hope this helps! $\endgroup$ Oct 9 '20 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.