Skip to content

geohash — Geohash

Every example on this page starts here

import polars as pl
import polars_hash as plh

Geohash encode, decode and neighbors, on pl.Expr as .geohash.

A geohash is a base-32 string. It gives the name of a rectangular cell on the earth. The prefixes are hierarchical: cell 9q60y contains every point whose geohash starts with 9q60y. A starts_with filter is therefore a query for a rectangular area, and two geohashes with a long identical prefix are near to each other.

The expressions that take coordinates read a Struct with a latitude field and a longitude field. Both fields must be Float32 or Float64, and polars-hash casts Float32 to Float64. It finds the fields by name, so their order is not important, and it ignores the other fields.

to_coords

to_coords() -> Expr

Decode a geohash string to the coordinates of the cell center.

If you encode a coordinate and then decode the geohash, the result is different from the initial coordinate. The difference is less than the size of the cell.

Returns:

Type Description
Expr

A Struct with two Float64 fields, longitude first and latitude second.

Note

from_coords() finds the fields of its input struct by name, but to_coords() writes longitude before latitude. Use unnest, or select the fields by name and not by position.

Raises:

Type Description
ComputeError

The string is not a geohash. A null row gives a struct of two null fields, and raises nothing.

Examples:

>>> df = pl.DataFrame({"h": ["9q60y60rhs"]})
>>> coords = df.select(plh.col("h").geohash.to_coords()).item()
>>> round(coords["longitude"], 4), round(coords["latitude"], 4)
(-120.6623, 35.3003)

from_coords

from_coords(len: int | str | Expr = 12) -> Expr

Encode a coordinate struct to a geohash string.

Parameters:

Name Type Description Default
len int | str | Expr

The number of characters, from 1 to 12. An int applies to every row. polars-hash reads a str as a column name and a pl.Expr as an expression, and the precision is then different for each row. All the integer types are permitted, signed and unsigned, and polars-hash casts the value to Int64. It also accepts a float and truncates it, so 5.9 gives 5.

12

Returns:

Type Description
Expr

Utf8.

Raises:

Type Description
ComputeError

len is less than 1 or more than 12 (Invalid length specified: 13. Accepted values are between 1 and 12, inclusive); len is null (Length may not be null); a coordinate is outside its range (invalid coordinate range: COORD(-120.6623 91.0)); or a coordinate field is not a float (Latitude input needs to be float). A null latitude or a null longitude gives null for that row, and raises nothing.

Note

Each character adds about 5 bits, so the cells become small quickly. A len of 1 covers about 5000 × 5000 km, 3 covers 156 × 156 km, 5 covers 4.9 × 4.9 km, 7 covers 153 × 153 m, 9 covers 4.8 × 4.8 m, and 12 covers 3.7 × 1.9 cm.

Examples:

>>> df = pl.DataFrame(
...     {"coord": [{"longitude": -120.6623, "latitude": 35.3003}]},
...     schema={
...         "coord": pl.Struct(
...             [
...                 pl.Field("longitude", pl.Float64),
...                 pl.Field("latitude", pl.Float64),
...             ]
...         )
...     },
... )
>>> df.select(plh.col("coord").geohash.from_coords(5)).item()
'9q60y'

A column name or an expression gives one precision for each row:

>>> df.with_columns(n=pl.lit(3)).select(
...     plh.col("coord").geohash.from_coords("n")
... ).item()
'9q6'

neighbors

neighbors() -> Expr

Give the eight geohash cells around a cell.

The neighbor cells have the precision of the input cell. Use this expression to find near points: a point near the edge of a cell can have near points in an adjacent cell, and a search over the cell and its eight neighbors also finds those points.

Returns:

Type Description
Expr

A Struct with eight Utf8 fields in this order: n, ne, e, se, s, sw, w, nw.

Raises:

Type Description
ComputeError

The string is not a geohash. A null row gives a struct of eight null fields, and raises nothing.

Examples:

>>> df = pl.DataFrame({"h": ["sp1xk2m6194y"]})
>>> df.select(plh.col("h").geohash.neighbors()).item()["n"]
'sp1xk2m6194z'