What does SPI measure?
The surveillance performance index (SPI) compares a district’s current reporting with its earlier reporting, then compares that change with the national pattern. It uses non-polio acute flaccid paralysis (NPAFP) case counts and the population under 15.
It is calculated in three steps:
- Estimate the expected number of NPAFP cases from the district’s own earlier reporting and its current under-15 population.
- Divide the reported cases by the expected cases. This is the district’s observed-to-expected (O/E) ratio.
- Divide the district’s ratio by the national ratio for the same year.
An SPI of 1 means the district’s ratio equals the national ratio. An SPI of 0.6 means the district’s ratio is 60% of the national ratio. Check both ratios to see whether reporting fell below earlier levels: an SPI below 1 can also occur when reporting increased nationally but increased less in the district.
How is it different from the NPAFP rate?
The conventional NPAFP rate is the number of reported cases per 100,000 children under 15 per year. It is compared with a fixed target, such as 3, regardless of the district’s earlier reporting.
SPI compares each district with its own history and the national ratio. A district can report fewer cases than expected from earlier years and still meet the NPAFP target. SPI can identify this decline if it is larger than the national decline. A district that has reported few cases for years can have an SPI near 1 while staying below the NPAFP target.
The two measures answer different questions, so read them together.
Interpreting SPI works through
examples, and spi_compare_npafp() places each district-year
in one of the four combinations.
Which SPI should I use?
The package calculates expected counts in two ways. Both use earlier reporting, and the resulting SPI values have the same interpretation.
| Simple SPI | Model-based SPI | |
|---|---|---|
| Function | spi_simple() |
spi_index() |
| Expected count from | The district’s own earlier rate | A spatial and temporal model |
| District reporting history | Yes | Yes |
| Statistical model | No | Yes |
| INLA | No | Yes |
| Boundary files | No | Yes, or a neighbour graph |
| Input counts | Annual | Monthly |
| Uncertainty intervals | No | Yes |
| Short or sparse history | SPI unavailable without an earlier case | More stable estimates |
| Monthly estimates | No | Yes |
| Comparison with the NPAFP target | Yes | Yes |
| STEPS field guide | Yes; default SPI cutoff of 0.5 | Yes; uses the credible interval |
Start with the simple SPI for annual results. You can check each value by hand using case counts, population and the national ratio.
Use the model-based SPI when you need uncertainty intervals, monthly estimates, or more stable expected counts for districts with little reporting history.
A first example
The bundled synth_surveillance data cover 236 districts
in the fictional country Harad, from 2015 to 2024. The case counts are
monthly, so first add them up by year:
library(spi)
annual <- synth_surveillance$cases |>
dplyr::mutate(year = as.integer(format(month, "%Y"))) |>
dplyr::summarise(count = sum(count), .by = c(adm2_guid, year))Then calculate the simple SPI, naming the columns that hold the district ID, the case count and the under-15 population:
spi_results <- spi_simple(
data = annual,
population = synth_surveillance$population,
id_col = "adm2_guid",
count_col = "count",
pop_col = "pop_u15",
verbose = FALSE
)
spi_resultstibble::as_tibble(spi_results) gives one row per
district and year with the observed and expected counts, both ratios and
the SPI.
Compare the SPI with the NPAFP target:
comparison <- spi_compare_npafp(spi_results, npafp_target = 3, verbose = FALSE)
comparison$metrics |>
dplyr::select(n, n_neither, n_spi_only, n_npafp_only, n_both)
#> # A tibble: 1 x 5
#> n n_neither n_spi_only n_npafp_only n_both
#> <int> <int> <int> <int> <int>
#> 1 1644 678 742 42 182n_spi_only counts district-years that met the NPAFP
target but had an SPI below 1. Their observed-to-expected ratio was
below the national ratio, even though they met the reporting target.
Where to go next
For either SPI:
- Preparing data for SPI shows how to build the input tables.
- Using SPI with POLIS data starts from the POLIS AFP line list.
- Interpreting SPI explains what the results mean and what they do not.
- How SPI works explains both calculations and their limitations.
For the simple SPI, Calculating the simple SPI works through three districts by hand and repeats the calculation in R.
For the model-based SPI, Calculating the model-based SPI fits the model, Model options and sensitivity covers the model choices, and Using SPI for district review runs the STEPS field guide.