svy: Python Package for Complex Survey Design and Analysis

Design-based inference for stratified, cluster, and multi-stage surveys

Documentation
Survey Analysis
Python
Statistics
Professional Python toolkit for designing complex surveys, calculating sample sizes, weighting survey data, and performing statistical analysis with stratified, cluster, and multi-stage sampling designs.
Author

Mamadou S. Diallo, Ph.D.

Published

January 18, 2026

Modified

August 15, 2026

Keywords

complex survey analysis Python, survey design Python package, stratified sampling Python, cluster sampling analysis, PPS sampling Python, survey weighting calibration, variance estimation surveys, design-based inference, Taylor linearization Python, survey bootstrap replication, multi-stage sampling design, probability sampling Python, survey statistics Python, American Community Survey (ACS), Current Population Survey (CPS), National Health and Nutrition Examination Survey, National Health Interview Survey (NHIS), Behavioral Risk Factor Surveillance System (BRFSS), Demographic and Health Survey (DHS), Multiple Indicator Cluster Survey (MICS), European Social Survey (ESS), official statistics, opinion polling Python, R survey package Python alternative, svydesign Python, survey sampling Python, weighted survey estimation Python

What is svy?

svy is a Python package for the design and analysis of complex survey data. When surveys use stratification, clustering, or unequal probability selection, standard software produces incorrect standard errors. svy accounts for the actual sampling design to provide correct design-based estimates (means, totals, proportions, regression models, and more).

svy is designed for modern survey research workflows; it provides good performance, reproducible runs, and convenient pipelines (chains of processing and analysis actions).

Get Started → Browse Tutorials → Source Code ↗

pip install svy
# or, with uv:
uv add svy

Install svy[report] (rather than plain svy) for rich, pretty-printed output.

Quick Start

The examples below run against a small example survey bundled with svy — a subset of a synthetic World Bank household survey. It loads offline, so you can copy‑paste and run everything without any download or setup. See Example Datasets for the full data and how to use your own.

import svy

# Load a bundled example survey (runs offline)
sample_df = svy.datasets.load("hld_sample_wb_2023", source="bundled")

# Describe the complex sampling design
design = svy.Design(
    stratum=("geo1", "urbrur"),  # stratification
    psu="ea",                    # primary sampling units (clusters)
    wgt="hhweight",              # survey weights
)
sample = svy.Sample(data=sample_df, design=design)

print(sample)
╭────────────── Sample ───────────────╮
 Survey Data                         
   Rows     : 825                    
   Columns  : 19                     
   Strata   : 7                      
   PSUs     : 33                     
                                     
 Survey Design                       
   Row index          svy_row_index  
   Stratum            (geo1, urbrur) 
   PSU                ea             
   SSU                None           
   Weight             hhweight       
   With replacement   False          
   Prob               None           
   Hit                None           
   MOS                None           
   Population size    None           
   Replicate weights  None           
╰─────────────────────────────────────╯
# Population mean of per-capita expenditure, with a design-based standard error
estimate = sample.estimation.mean("pc_exp")

print(estimate)
╭───────────────── Estimate: MEAN (TAYLOR) ──────────────────╮
                                                            
         est         se          lci          uci   cv (%)  
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━  
  3,810.0716   216.5374   3,364.9725   4,255.1706     5.68  
                                                            
╰────────────────────────────────────────────────────────────╯
# Every result exports to a polars DataFrame for further processing
# (to_polars() is available on most svy result objects)
estimate.to_polars()
shape: (1, 6)
est se lci uci cv df
f64 f64 f64 f64 f64 i64
3810.071566 216.537414 3364.972537 4255.170595 0.056833 26

The estimate carries the correct design-based standard error, 95% confidence interval, and coefficient of variation. The same design flows into regression:

# Regression that accounts for the sampling design
model = sample.glm.fit(
    y="pc_exp",
    x=["hhsize", svy.Cat("urbrur")],
    family="gaussian",
)

print(model)
╭────────────────────────────── GLM: Gaussian (identity) ───────────────────────────────╮
 Modeling: pc_exp                                                                      
                                                                                       
 Observations         825  AIC           15036.6628                                    
 DF Residuals          24  BIC                    -                                    
 Deviance      3.8943e+09  Scale         1.4978e+08                                    
 R-squared        0.33031  R-sq (adj)       0.32868                                    
                           Iterations             2                                    
 F-stat (adj)    32.35628  Prob (F-adj)      <0.001                                    
                                                                                       
                                                                                       
  Term                Coef.    Std.Err.          t    P>|t|       [0.025       0.975]  
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━  
  _intercept_    4518.57690   323.10229   13.98497   <0.001   3851.72655   5185.42726  
  hhsize         -549.91031    80.87000   -6.79993   <0.001   -716.81779   -383.00283  
  urbrur_Urban   2141.91357   303.01807    7.06860   <0.001   1516.51502   2767.31213  
                                                                                       
╰───────────────────────────────────────────────────────────────────────────────────────╯
Tip📌 Validated against R

svy produces numerically identical results to R’s survey package across Taylor linearization, BRR, bootstrap, and jackknife methods. Read the validation study →

Coming from R?

If you use R’s survey package, svy maps directly to the same concepts:

R (survey package) svy (Python)
svydesign() svy.Design() + svy.Sample()
svymean() sample.estimation.mean()
svytotal() sample.estimation.total()
svyglm() sample.glm.fit()
as.svrepdesign() svy.Design(rep_weights=...)

Results are validated to be numerically equivalent. See the full validation study and the getting started guide for a side-by-side comparison.

Core Capabilities

Data Wrangling

Rename, categorization, recoding, top- and bottom-coding, labelling. → Wrangling tutorial

Survey Design & Planning

Calculate required sample sizes, perform power analysis, and allocate samples optimally across strata. → Planning tutorial

Sample Selection

Draw probability samples using SRS, systematic, PPS, stratified, and multi-stage designs. → Selection tutorial

Survey Weighting

Compute design weights, adjust for nonresponse, and calibrate using poststratification, raking, and GREG. → Weighting tutorial

Replicate weights (Bootstrap, BRR, and Jackknife). → Replicate weights

Statistical Estimation

Estimate means, totals, proportions, ratios, and medians with Taylor linearization or replicate weight variance. → Estimation tutorial

Categorical Data Analysis

Tabulation, crosstabulation, t-tests. → Categorical Data Analysis tutorial

Regression Modeling

Fit linear, logistic, and Poisson GLMs with design-adjusted standard errors. → GLM tutorial

Who Uses svy?

svy is built for the communities that work with complex survey data:

  • 📊 Survey methodologists: national statistics offices, sampling design work
  • 📈 Biostatisticians: NHANES, BRFSS, DHS, and other public health surveys
  • 🎓 Social scientists: household surveys, labor force studies, demographic research
  • 🏛️ Government statisticians: official statistics production
  • 🗳️ Pollsters & election analysts: opinion polling, exit polls, campaign and partisan surveys
  • 🔬 Epidemiologists: prevalence estimation, risk factor analysis
  • 👨‍🏫 Educators: teaching survey sampling and design-based inference

Documentation

Installation pip, uv, virtual environments
Getting Started First analysis in 10 minutes
Quick Tour The Sample object explained
Tutorials Full workflow, step by step

The svy Ecosystem

svy is the core library, but it’s part of a larger ecosystem of companion packages. Each of these standalone libraries extends the core survey library into a specialized area:

svy-sae Small area estimation
svy-io Read SPSS, Stata, SAS files

Reading your own data is built into core svy — svy.io.read_csv for CSV files, plus bundled example surveys via svy.datasets.load. The standalone svy-io package adds support for proprietary formats such as SPSS, Stata, and SAS.

Frequently Asked Questions

Is svy a Python alternative to R’s survey package?

Yes. svy is designed to provide equivalent design-based inference to R’s survey package with a Pythonic API. Results have been validated to be numerically identical. See the validation study.

Can I use svy to analyze NHANES, DHS, or BRFSS data?

Yes. svy is built for exactly these surveys. It supports the complex stratified cluster designs used by NHANES, DHS, BRFSS, and similar large-scale public health and demographic surveys.

Does svy support replicate weights?

Yes. svy supports Bootstrap, Balanced Repeated Replication (BRR), Jackknife, and Successive Difference Replication (SDR) replicate weight methods for variance estimation. See the replicate weights tutorial.

What is design-based inference and why does it matter?

Design-based inference accounts for how the sample was drawn (stratification, clustering, unequal probabilities) when calculating standard errors. Ignoring the design typically underestimates standard errors, producing falsely narrow confidence intervals and incorrect hypothesis tests. This can lead to poor decisions.

Is svy production-ready?

Core functionality for survey design, weighting, and variance estimation is stable and production-ready. The API continues to mature. See the development status note below.

How does svy differ from samplics?

svy supersedes samplics, an earlier library by the same author. svy provides a unified Sample object, expanded methodology (GLMs, SAE, data I/O), and active long-term support. samplics is archived.

Development Status

svy is under active development. Core survey design, weighting, and variance estimation are stable and production-ready. APIs and documentation continue to mature.

📧 Feedback: info@svylab.com  ·  🐛 Issues: GitHub Issues

Community & Support

TipHelp make svy the standard for survey analysis in Python

Starring the repository helps signal demand and prioritize validation and stability work. → Star svy on GitHub

Academic Citation

@software{svy2026,
  title   = {svy: Python Package for Complex Survey Analysis},
  author  = {Diallo, Mamadou S.},
  year    = {2026},
  url     = {https://github.com/samplics-org/svy},
  version = {0.19.0}
}

License

svy is open source software released under the MIT License. See LICENSE for full terms.