Tutorials
Step-by-step usage examples.
Simplified Database Functions
Use an origin namespace to fetch data — the data source is explicit:
import pysus
# Download SINAN Dengue data (DATASUS FTP, via the S3 catalog mirror)
df = pysus.ftp.sinan(disease="deng", year=2000)
# Multiple years
df = pysus.ftp.sinan(disease="deng", year=[2023, 2024])
# SINASC births for São Paulo (dados.gov.br)
df = pysus.dadosgov.sinasc(state="SP", year=[2020, 2021, 2022, 2023])
# SIM mortality data
df = pysus.ftp.sim(state="SP", year=2024)
# SIH hospitalizations with month filter
df = pysus.ftp.sih(state="SP", year=2024, month=[1, 2, 3])
# CNES health facilities
df = pysus.ftp.cnes(state="SP", year=2024, month=1)
The as_dataframe=True fetchers above return a single concatenated
pandas.DataFrame. See the FileBag Workflow
section below for how to inspect files before downloading or work with the
downloaded files individually.
FileBag Workflow
A namespaced fetcher returns either a high-level FileBag or a
DataFrame:
download=False→ a remoteFileBaglisting the files that would be fetched, without downloading anything (as_dataframeis ignored here).download=True(default) +as_dataframe=False→ a localFileBagof downloaded files.as_dataframe=True→ a single concatenatedpandas.DataFrame.
A FileBag is synchronous — the underlying async client is started and
awaited internally:
import pysus
# 1. List what would be downloaded (nothing is fetched yet)
bag = pysus.ftp.sinan(disease="deng", year=2020, download=False)
print(bag)
# Files[DENGBR20.parquet (remote)]
# 2. Inspect individual files (path, type, dataset, ...)
f = bag[0]
print(f.path) # public/data/ftp/sinan/DENG/2020/_/BR/DENGBR20.parquet
# 3. Download all (or a subset) -> a local FileBag
local = bag.download() # Files[DENGBR20.parquet]
# local = bag.download(indexes=[0]) or bag.download_one(0)
# 4. Concatenate the downloaded tabular files into one DataFrame
df = local.to_dataframe() # same as local.df
print(df.shape) # (975842, 121)
len/iter/[] (including slices) and paths let you introspect a
bag, and kind tells you whether it holds "remote" or "local"
files. Remote bags from URL-only origins (e.g. pysus.saude.*) also
support this workflow.
OpenDataSUS (Saude) Functions
import pysus
# Dengue/Chik/Zika notifications from OpenDataSUS
df = pysus.saude.arboviroses(disease="dengue", year=2024)
# Vaccination coverage
df = pysus.saude.vacinacao(state="SP", year=2024)
# Hospital and health facility data
df = pysus.saude.assistencia_saude(state="SP", year=2024)
# Primary care (Previne Brasil)
df = pysus.saude.atencao_primaria(state="SP", year=2024)
# Nutrition surveillance
df = pysus.saude.sisvan(state="SP", year=2024)
Discovery
from pysus import info_table, search, list_files
# Browse available datasets
info_table()
# Search for datasets by keyword
results = search("dengue")
# List files in a dataset
df = list_files("SINAN", group="DENG", year=2024)
Discovery is also scoped per origin:
import pysus
pysus.ftp.info() # FTP origin datasets
pysus.ftp.list_files("SINAN", year=2024, state="RJ")
pysus.dadosgov.get_origin_meta() # origin metadata
Using the PySUS Client
from pysus import PySUS
async def main():
async with PySUS() as pysus:
# Query DuckLake catalog
files = await pysus.query(
dataset="sinan",
group="DENG",
state="SP",
year=2024,
)
# Download files
for f in files:
local = await pysus.download(f)
print(local.path)
# Read multiple parquet files
import glob
paths = glob.glob("/cache/sinan/**/*.parquet")
df = pysus.read_parquet(paths, mode="union")
Parallel Downloads
# Download many files in parallel
downloaded = await pysus.download_many(files, max_concurrent=5)
read_parquet Modes
# Union (default) - all columns from any file
df = pysus.read_parquet(paths, mode="union")
# Intersection - only common columns across all files
df = pysus.read_parquet(paths, mode="intersection")
# Strict - raises error if schemas don't match
df = pysus.read_parquet(paths, mode="strict")
# With custom SQL filter
df = pysus.read_parquet(paths, sql="SELECT * WHERE column > 100")
Data Quality
from pysus import column_stats, missing_values, quality_score, validate_data
# Per-column statistics (types, nulls, uniques, sample values)
stats = column_stats(df)
# Missing value summary
missing = missing_values(df)
# Overall quality score (0-100)
score = quality_score(df)
# Validate data against expected schema
issues = validate_data(df, dataset="SINAN")
Data Transformation
from pysus import (
aggregate_by_age_group,
aggregate_by_period,
aggregate_by_state,
detect_units,
optimize_memory,
rename_columns,
to_english,
)
# Aggregate cases by age group
grouped = aggregate_by_age_group(df, age_col="IDADE", period_col="DT_NOTIFIC")
# Detect measurement units in columns
units = detect_units(df)
# Rename columns with a mapping
df = rename_columns(df, mapping={"DT_NOTIFIC": "notification_date"})
# Convert Portuguese column/value names to English
df_en = to_english(df)
# Optimize memory usage
df = optimize_memory(df)
Column Metadata
from pysus import search_columns, load_column_metadata, available_databases
# List curated schema databases
print(available_databases()) # ["sim", "sinan"]
# Load columns for a specific SINAN disease
columns = load_column_metadata("sinan", "Dengue")
# Search for a column across all datasets
results = search_columns("CON_CLASSI")
for r in results:
print(r.dataset, r.name, r.categories)
Export
from pysus import export, to_csv, to_excel, to_geojson, to_sql
# Export to various formats
to_csv(df, "output.csv")
to_excel(df, "output.xlsx")
to_geojson(df, "output.geojson", lat_col="LATITUDE", lon_col="LONGITUDE")
# Full export with options
export(df, "output.csv", compression="gzip")
Data Diff
from pysus import diff_dfs, diff_summary, diff_rows
# Compare two DataFrames
diff = diff_dfs(df_old, df_new)
# Summary of differences
summary = diff_summary(df_old, df_new)
# Row-level differences
rows = diff_rows(df_old, df_new)
Cache Management
from pysus import cache_status, clear_cache
# Show cache statistics
cache_status()
# Clear all cached files
clear_cache()