Preparing Unit-Level Inputs in Python with svy-sae
Household records from the survey, the same covariates from the census
Tutorials
Unit-level
Python
Prepare the inputs of a unit-level small area model in Python: household records and covariates from a survey, the same covariates for every census household, and district means for EBLUP with svy-sae.
Author
Mamadou S. Diallo, Ph.D.
Modified
November 5, 2026
Keywords
unit-level small area estimation Python, census auxiliary data, household survey covariates, EBLUP EBP inputs, poverty mapping Python
WarningAbout these examples
This tutorial illustrates the svy-sae API; it is not a rigorous small area analysis. The models are kept simple so each step stays readable, and in many places, from the choice of covariates to the variance model, better choices could be made to improve them.
Area-level models start from one direct estimate per area. Unit-level models start from the survey records themselves: they fit a regression of the outcome on covariates across the sampled units, with an effect for each area, and use it to predict every unit of the population that was not sampled. The covariates must therefore be known for every unit of the population, typically from a census, and measured the same way in the survey and the census.
This tutorial prepares the inputs used by every unit-level tutorial that follows: household records from the survey, the same household covariates for every census household, and their district means. The survey, districts, and census are those of the area-level tutorials, so the two approaches can be compared on the same districts.
Setting up the sample
We use the synthetic household survey and census of an imaginary country (World Bank 2023b, 2023a):
import polars as plimport svyimport svy_sae as saehld_data = svy.datasets.load("hld_sample_wb_2023").datahld_census = svy.datasets.load("hld_pop_wb_2023").dataprint(f"Survey households: {hld_data.height:,}")print(f"Census households: {hld_census.height:,}")
Survey households: 8,000
Census households: 2,501,755
The outcome is total household expenditure per person. A household is poor when it falls below 1,800, the poverty line of the area-level tutorials and of svy’s estimation tutorial.
NoteMethod note
The data also have a pc_exp column, defined differently. We use tot_exp / hhsize so that the poverty rates match those of the area-level tutorials.
Household covariates
The covariates must be built the same way in both files. Define them once and apply the same function to the survey and the census:
These are the household-level versions of the district shares used as area-level covariates: a district’s share of households with piped water is the mean of piped_water over its households.
Are they measured alike?
A covariate that means something different in the survey and the census biases every prediction. One check: the survey’s weighted estimate of each covariate should agree with the census value, within sampling error.
z is the difference in standard errors. The share of urban households matches exactly, but the survey reports more of every asset than the census, by up to about three standard errors. Differences that large, all in the same direction, are a pattern rather than sampling noise. With real data they call for a look at the questionnaires and reference dates before these covariates enter the model; here we keep them, as the tutorials illustrate the API rather than a full analysis.
Population data
The models need the census in one of two forms. The household records, one row per household:
World Bank. 2023a. “Synthetic Data for an Imaginary Country, Full Population, 2023.” World Bank, Development Data Group. https://doi.org/10.48529/78M1-AE09.
———. 2023b. “Synthetic Data for an Imaginary Country, Sample, 2023.” World Bank, Development Data Group. https://doi.org/10.48529/MC1F-QH23.