How to Calculate the Positive Predictive Value of a PCR test

How to Calculate the Positive Predictive Value of a PCR test

December 21, 2021

The issue of false positive rates of the PCR test has generated a great amount of controversy over the last two years, because the PCR test has been the centerpiece of fear campaign. But a more relevant metric for a PCR test is its positive predictive value, or PPV. This is the probability that a person testing positive actually has the disease. In other words, if the PPV were 50%, then the test would be no better than flipping a coin to determine if you actually had the disease after testing positive.

In order to calculate the PPV of a test, we need to know three things:

  • the test’s sensitivity, which tells us the true positive and false negative rates
  • the test’s specificity, which tells us the false positive and true negative rates
  • the seroprevalence of the disease, i.e., the actually percentage of the population that has the disease

This video by Dr. Roger Seheult explains the method used to calculate the PPV using very clear diagrams. Skip to the 2:20 point:

As you will see from the first example presented by Dr. Seheult, if the sensitivity is 90%, the specificity is 95%, and the seroprevalence is 5% (which is low), the PPV wiill be 47%, which is about like flipping a coin. As the seroprevalence goes up, the PPV also goes up.

This can be understood intuitively: if, say, only 5% of people in the population have the disease, and the test has a false positive rate of 5%, then if you test positive, you’re not going to be able to tell if you’re in the half of the people that got false positives, or in the half of the people who actually have the disease. This is a gross oversimplification of the math involved, but gives the general idea. I highly recommend watching Dr. Seheult’s video. Try working out your own examples on paper, as I did.

I have also written a Ruby program that calculates the PPV given the three characteristics of a test that we need. This program is probably overly complicated, because I wanted to have it follow the method shown by Dr. Seheult. But it does give the correct answers:

#!/usr/bin/ruby

# Calculate the Positive Predictive Value and Negative
# Predictive Value for a PCR test.

# Get a float number from standard input

def getPercentage(prompt)
  while true
    print prompt + " percentage (1-100): "
    n = gets.to_f
    if n < 1 || n > 100
      puts "Number must be between 1 and 100"
    else
      return n / 100
    end
  end
end

sensitivity = getPercentage("Sensitivity")
specificity = getPercentage("Specificity")
prevalence  = getPercentage("Seroprevalence")

# Use an arbitrary population of 1000, though it could be
# any largish number.

population = 1000

# First, use the prevalence to calculate the number of people who
# have the disease (dplus).  From that, and the sensitivity, we can get the true
# positives (tp) and false negatives (fn).

dplus  = population * prevalence
#puts "dplus = #{dplus}"
tp = dplus  * sensitivity
#puts "tp = #{tp}"
fn = dplus - tp
#puts "fn = #{fn}"

# Now use the specificity and the number of people who don't have
# the disease (dminus) to calculate the true negatives (tn).
# From that, we can get the false positives (fp).

dminus = population - dplus
#puts "dminus = #{dminus}"
tn = dminus * specificity
#puts "tn = #{tn}"
fp = dminus - tn
#puts "fp = #{fp}"

# Now calculate the number of people who tested positive (tplus) and the number
# of people who tested negative (tminus).  These are the sums of both the false
# and true positives or negatives.

tplus  = tp + fp
#puts "tplus = #{tplus}"
tminus = fn + tn
#puts "tminus = #{tminus}"

# The positive predictive value is the number of people who are actually
# positive divided by the number who tested positive.

ppv = (tp / tplus * 100).round.to_i
puts "PPV = #{ppv}%"

# The negative predictive value is the number of people who are actually
# negative divided by the number who tested negative.

npv = (tn / tminus * 100).round.to_i
puts "NPV = #{npv}%"