Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions docs/group-by-place.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Group records by place

A Nigerian postcode says where a building is at five levels: state, LGA, district, area, and building. Cut a code off after one of those and you have a prefix that every building in that place shares. Counting customers, deliveries, or cases by district is then an ordinary group-by, with no map and no boundary files.

| Cut after | Prefix of `EK-01-A03-FK-01` |
| --- | --- |
| State | `EK` |
| LGA | `EK-01` |
| District | `EK-01-A03` |
| Area | `EK-01-A03-FK` |

## In Python

```python
from collections import Counter

from ng_postcode import Postcode, Segment, parse


def district(text: str) -> str | None:
"""The district a code is in, or None for one that is not well formed."""
code = parse(text)
return str(code.truncate(Segment.DISTRICT)) if isinstance(code, Postcode) else None


rows = ["EK-01-A03-FK-01", "ek 01 a03 zz 14", "LA11W06TC10", "not a code"]
print(Counter(map(district, rows)))
# Counter({'EK-01-A03': 2, 'LA-11-W06': 1, None: 1})
```

The same function works on a column:

```python
frame["postcode"].map(district).value_counts(dropna=False) # pandas
table.group_by(pl.col("postcode").map_elements(district, return_dtype=pl.String)).len() # Polars
```

Rows that are not well-formed codes come out under `None`, so they are counted and visible.

## In SQL

```sql
SELECT ng_postcode_format(ng_postcode_truncate(postcode, 'district')) AS district, count(*)
FROM customers
GROUP BY 1;
```

The functions for PostgreSQL and DuckDB are in [`sql/`](https://github.com/Adeniyikayodee/ng-postcode/tree/main/sql).

## What a prefix does not tell you

A prefix groups buildings that NIPOST placed in the same district or area. It carries no name, boundary, or population. Names come from NIPOST's lookup, and a well-formed code is not necessarily assigned to a building.
4 changes: 4 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ When one system or AI agent hands a location to another, send it as a postcode r

For a whole address, wrap the reference in an [address record](address-record.md). It adds the names and lines that other formats need, and maps onto ISO 20022, FHIR, schema.org, and vCard.

## Group records by place

Every building in a district shares the start of its code, so counting records by state, LGA, district, or area is an ordinary group-by with no map. See [Group records by place](group-by-place.md) for Python, pandas, Polars, and SQL.

## The format

| Segment | Example | Shape |
Expand Down
1 change: 1 addition & 0 deletions docs/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Since 1 October 2026 a Nigerian building's postcode is this 11-character code. A
- [ng-address-resolver](https://pypi.org/project/ng-address-resolver/): `pip install ng-address-resolver`. Resolves free-text Nigerian addresses to postcodes, only as precisely as the evidence allows. Pre-release.
- [WooCommerce plugin](https://github.com/Adeniyikayodee/ng-postcode-woocommerce): checks and tidies the postcode at checkout, finds it from the customer's location, and makes shipping zones match on postcode prefixes.
- [SQL](https://github.com/Adeniyikayodee/ng-postcode/tree/main/sql): the postcode as a PostgreSQL domain and DuckDB macros, with `ng_postcode_parse`, `ng_postcode_format`, and `ng_postcode_truncate` for grouping by state, LGA, district, or area.
- [Group records by place](https://adeniyikayodee.github.io/ng-postcode/group-by-place): count or select records by state, LGA, district, or area by cutting each code to a prefix with `truncate`.

## Docs

Expand Down
1 change: 1 addition & 0 deletions docs/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Since 1 October 2026 a Nigerian building's postcode is this 11-character code. A
- [ng-address-resolver](https://pypi.org/project/ng-address-resolver/): `pip install ng-address-resolver`. Resolves free-text Nigerian addresses to postcodes, only as precisely as the evidence allows. Pre-release.
- [WooCommerce plugin](https://github.com/Adeniyikayodee/ng-postcode-woocommerce): checks and tidies the postcode at checkout, finds it from the customer's location, and makes shipping zones match on postcode prefixes.
- [SQL](https://github.com/Adeniyikayodee/ng-postcode/tree/main/sql): the postcode as a PostgreSQL domain and DuckDB macros, with `ng_postcode_parse`, `ng_postcode_format`, and `ng_postcode_truncate` for grouping by state, LGA, district, or area.
- [Group records by place](https://adeniyikayodee.github.io/ng-postcode/group-by-place): count or select records by state, LGA, district, or area by cutting each code to a prefix with `truncate`.

## Docs

Expand Down
Loading