Skip to main content

Nigerian Polling Units

ngpu is a Python and R programming library that provides hierarchical intelligence over Nigeria’s polling unit administrative structure, designed specifically for machine learning, analytics, and research workflows.

Features

  • Programmatic access to States, LGAs, Wards, and Polling Units
  • ML-ready DataFrame export
  • Hierarchical categorical encoders
  • Coverage and bias diagnostics
  • Fuzzy search for noisy text inputs

Installation

For Python Users: Run in notebook or IDE

pip install ngpu

For R Users: Run in terminal or Anaconda Prompt

conda create -n ngpu-r -c conda-forge python=3.10 ngpu r-base r-reticulate pandas scikit-learn

This installs:

Python

ngpu

R

reticulate

ML dependencies

Quick Start

from ngpu import Index, to_dataframe

states = Index.states()
lgas = Index.lgas("Anambra")

df = to_dataframe()

Connecting R to ngpu

Open R or RStudio.

library(reticulate)

use_condaenv("ngpu-r", required = TRUE)

ngpu <- import("ngpu")

Machine Learning Usgae

from ngpu.ml.encoder import PollingUnitEncoder

encoder = PollingUnitEncoder(level="ward")
X = encoder.fit_transform(df)

Coverage Diagnostics

from ngpu.ml.diagnostics import CoverageReport

report = CoverageReport(df)
report.coverage_by_state()

Use Cases

Regional ML feature engineering

Bias and coverage analysis

Socio-economic modeling

Civic tech and policy research

Any domain requiring stable Nigerian administrative anchors

In Python

List all states:

from ngpu import Index

states = Index.states()
print(states)

⬆ Validate categorical values in incoming datasets.

Get LGAs for a state:

lgas = Index.lgas("Enugu")
print(lgas)

⬆ Fill missing LGA values during data cleaning.

Get wards and polling units

wards = Index.wards("Enugu", "Awgu")
pus = Index.polling_units("Enugu", "Awgu", "Ward 1")

⬆ Hierarchical drill-down analysis.

Converting to a DataFrame:

df = ngpu.to_dataframe()
df.head()

Join with survey data

Join with transaction data

Feature engineering pipelines

Problem

Dataset contains:

state Missing lga, ward, polling_unit

Solution

import pandas as pd

data = pd.DataFrame({
    "state": ["Lagos", "Kano"]
})

ngpu_df = ngpu.to_dataframe()

enriched = data.merge(ngpu_df, on="state", how="left")

Result:

All valid LGAs, wards, and polling units are added

No manual mapping required

Machine Learning

Hierarchical Encoding

from ngpu.ml import PollingUnitEncoder

encoder = PollingUnitEncoder()

encoded = encoder.fit_transform(
    state="Lagos",
    lga="Ikeja",
    ward="Ward 1",
    polling_unit="PU 001"
)

print(encoded)

Use Case

Converts hierarchy into numeric features

Compatible with scikit-learn models

ML Pipeline

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

X = ngpu_df[["state", "lga", "ward"]]
y = ngpu_df["polling_unit"]

encoder = PollingUnitEncoder()
X_encoded = encoder.fit_transform_df(X)

X_train, X_test, y_train, y_test = train_test_split(
    X_encoded, y, test_size=0.2
)

model = RandomForestClassifier()
model.fit(X_train, y_train)

Data Validation & Diagnostics

from ngpu.ml import HierarchyDiagnostics

diag = HierarchyDiagnostics()

diag.validate(
    state="Lagos",
    lga="Gwale"
)

Returns:

True → valid

False → invalid

Use Case:

Detect bad records before training

Prevent invalid inference

In R

states <- ngpu$Index$states()
print(states)

⬆ Validate state names in a dataset before analysis.

lgas <- ngpu$Index$lgas("Lagos")
print(lgas)

⬆ Fill missing LGAs when only state information exists.

df <- ngpu$to_dataframe()
df_r <- py_to_r(df)

head(df_r)

⬆ Join ngpu data with survey, transaction, or demographic datasets.

Problem:

You have a dataset with: state missing lga, ward, polling_unit

Solution:

library(dplyr)

data <- data.frame(
  state = c("Lagos", "Kano")
)

ngpu_df <- py_to_r(ngpu$to_dataframe())

enriched <- data %>%
  left_join(ngpu_df, by = "state")

head(enriched)

Dataset is automatically expanded with valid LGAs, wards, and polling units.

Machine Learning Usage

encoder <- ngpu$PollingUnitEncoder()

encoded <- encoder$fit_transform(
  state = "Taraba",
  lga = "Jalingo",
  ward = "Ward 7",
  polling_unit = "PU 007"
)

print(encoded)

Convert categorical hierarchy into numeric ML-ready features

Used in regression, classification, and clustering.

Use with caret/tidymodels

library(caret)

ml_df <- ngpu_df %>%
  select(state, lga, ward) %>%
  mutate(across(everything(), as.factor))

model <- train(
  ward ~ .,
  data = ml_df,
  method = "rf"
)

Predict missing administrative attributes Learn regional patterns

Data Validation & Diagnotstics

diag <- ngpu$HierarchyDiagnostics()

diag$validate(
  state = "Lagos",
  lga = "Gwale"
)

Returns:

TRUE → valid

FALSE → impossible combination

Use case:

Catch data errors before modeling Prevent garbage-in-garbage-out ML

Common Errors & Fixes

Error: ModuleNotFoundError

use_condaenv("ngpu-r", required = TRUE)

Error: Wrong Python

py_config()

Ensure it points to ngpu-r.

Authors:

MaryBlessing Umeh, Software Engineer

Chidiebere V. Christopher, Data Scientist

LICENSE

MIT

Metadata

Release files for ngpu 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ngpu 0.1.0
File Size Uploaded
ngpu-0.1.0.tar.gz 907.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ngpu 0.1.0
File Interpreter ABI Platform
ngpu-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.8 MB

Release files / ngpu-0.1.0.tar.gz

Download URL ngpu-0.1.0.tar.gz
Size 907.6 kB
Tags Source
SHA-256 checksum
How to use checksums
c778a1473d3f880ca5e5884b9e771f2d2f70c261c6b60485d13a3fea6144193b
BLAKE2b-256 checksum
How to use checksums
fb1e823fb10cd7bd379813e278b210e57af93555f4091de0e152105ddfd0078a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release files / ngpu-0.1.0-py3-none-any.whl

Download URL ngpu-0.1.0-py3-none-any.whl
Size 911.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8498959711afd3cf091bc20dc2b89cf47100c5103b3addfe940467db22d95ba5
BLAKE2b-256 checksum
How to use checksums
2a4415f7755f925308efb3dbd72c0e7bc53a93127cf3af03a7dd7aae2f0ec0e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page