Skip to main content

This plugin provides stable hashing functionality across different polars versions.

📖 Documentation — every expression, its input and output types, and its arguments.

Examples

Cryptographic Hashers

import polars as pl
import polars_hash as plh

df = pl.DataFrame({
    "foo":["hello_world"]
})

result = df.select(plh.col('foo').chash.sha256())

print(result)

┌──────────────────────────────────────────────────────────────────┐
│ foo                                                              │
│ ---                                                              │
│ str                                                              │
╞══════════════════════════════════════════════════════════════════╡
│ 35072c1ae546350e0bfa7ab11d49dc6f129e72ccd57ec7eb671225bbd197c8f1 │
└──────────────────────────────────────────────────────────────────┘

Non-cryptographic Hashers

df = pl.DataFrame({
    "foo":["hello_world"]
})

result = df.select(plh.col('foo').nchash.wyhash())
print(result)
┌──────────────────────┐
│ foo                  │
│ ---                  │
│ u64                  │
╞══════════════════════╡
│ 16737367591072095403 │
└──────────────────────┘

result = df.select(plh.col('foo').nchash.farmhash64())
print(result)
┌──────────────────────┐
│ foo                  │
│ ---                  │
│ u64                  │
╞══════════════════════╡
│ 15605398435621216523 │
└──────────────────────┘

result = df.select(plh.col('foo').nchash.farmhash32())
print(result)
┌────────────┐
│ foo        │
│ ---        │
│ u32        │
╞════════════╡
│ 1719156559 │
└────────────┘

result = df.select(plh.col('foo').nchash.cityhash128())
print(result)
┌─────────────────────────────────────────┐
│ foo                                     │
│ ---                                     │
│ u128                                    │
╞═════════════════════════════════════════╡
│ 133423608296839006301901834072762183026 │
└─────────────────────────────────────────┘

result = df.select(plh.col('foo').nchash.gxhash64())
print(result)
┌─────────────────────┐
│ foo                 │
│ ---                 │
│ u64                 │
╞═════════════════════╡
│ 2180020304351407825 │
└─────────────────────┘

cityhash32() and cityhash64() return the values printed above for farmhash32() and farmhash64(). That is expected: FarmHash reuses CityHash for short input, and hello_world is 11 bytes. See the CityHash reference.

The GxHash expressions need a CPU with AES instructions and have no software fallback. Every x86, x86-64 and aarch64 wheel is built for them; there are no linux-armv7 or linux-ppc64le wheels from 0.8.0 on, because GxHash cannot be built for either. See the GxHash reference.

Geo Hashers

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.with_columns(
    plh.col('coord').geohash.from_coords().alias('geohash')
)
shape: (1, 2)
┌─────────────────────┬──────────────┐
│ coord               ┆ geohash      │
│ ---                 ┆ ---          │
│ struct[2]           ┆ str          │
╞═════════════════════╪══════════════╡
│ {-120.6623,35.3003} ┆ 9q60y60rhsgg │
└─────────────────────┴──────────────┘


pl.select(pl.lit('9q60y60rhs').geohash.to_coords().alias('coordinates'))
shape: (1, 1)
┌───────────────────────┐
│ coordinates           │
│ ---                   │
│ struct[2]             │
╞═══════════════════════╡
│ {-120.6623,35.300298} │
└───────────────────────┘

H3 Spatial Index

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.with_columns(
    plh.col('coord').h3.from_coords().alias('h3')
)
shape: (1, 2)
┌─────────────────────┬─────────────────┐
│ coord               ┆ h3              │
│ ---                 ┆ ---             │
│ struct[2]           ┆ str             │
╞═════════════════════╪═════════════════╡
│ {-120.6623,35.3003} ┆ 8c29adc423821ff │
└─────────────────────┴─────────────────┘

Time Hasher

Bins timestamps into variable-precision sliding windows of time, so rows that fall in the same window share a hash. Timestamps must lie between 1970-01-01 and 2098-01-01. A higher precision means a shorter window: 10 covers about 4 seconds, 8 about 4 minutes.

Precision may be 1 to 32, but past about 18 the hash stops changing for present-day timestamps and the extra characters are padding. The exact point depends on the date: timestamps close to 1970 keep splitting to about 21, far-future ones run out sooner.

from datetime import datetime

df = pl.DataFrame({"datetime": [datetime(2017, 2, 21, 20, 15, 13)]})

df.with_columns(
    plh.col('datetime').timehash.from_datetime().alias('timehash')
)
shape: (1, 2)
┌─────────────────────┬────────────┐
│ datetime            ┆ timehash   │
│ ---                 ┆ ---        │
│ datetime[μs]        ┆ str        │
╞═════════════════════╪════════════╡
│ 2017-02-21 20:15:13 ┆ afcccc0e1b │
└─────────────────────┴────────────┘


pl.select(pl.lit('afcccc0e1b').timehash.to_datetime().alias('datetime'))
shape: (1, 1)
┌────────────────────────────────┐
│ datetime                       │
│ ---                            │
│ datetime[μs, UTC]              │
╞════════════════════════════════╡
│ 2017-02-21 20:15:11.292315 UTC │
└────────────────────────────────┘


pl.select(pl.lit('afcccc0e1b').timehash.neighbors().alias('neighbors'))
shape: (1, 1)
┌─────────────────────────────┐
│ neighbors                   │
│ ---                         │
│ struct[2]                   │
╞═════════════════════════════╡
│ {"afcccc0e1a","afcccc0e1c"} │
└─────────────────────────────┘

Create hash from multiple columns

df = pl.DataFrame({"foo": ["hello_world"], "bar": ["today"]})

result = df.select(plh.concat_str("foo", "bar").chash.sha256())

Hash a whole row

hash_rows gives each row bytes that no other row can make, for all column types. Any hasher then reads those bytes.

df = pl.DataFrame(
    {"foo": ["hello_world"], "bar": [42], "baz": [[1, 2, 3]], "qux": [{"a": 1}]}
)

df.select(plh.hash_rows(pl.all()).chash.sha2_256())
shape: (1, 1)
┌──────────────────────────────────────────────────────────────────┐
│ foo                                                              │
│ ---                                                              │
│ str                                                              │
╞══════════════════════════════════════════════════════════════════╡
│ 9055866af8d3c113e0a8fdb729ce8e6fa67ed5f6f51efa8235a588e88ea972f4 │
└──────────────────────────────────────────────────────────────────┘

The encoder reads the meaning of a value, not the polars storage of it. An Int32 and the Int64 next to it make the same hash. A Datetime in milliseconds and the same time in nanoseconds also make the same hash, and a Categorical makes the hash of its string. The encoder does not read the column names. Therefore a new name keeps the hash, but a new order does not. The reference gives all the rules and the byte layout of version 1, which does not change.

Metadata

Release files for polars-hash 0.9.2

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

Source distribution (sdist)

Source distribution for polars-hash 0.9.2
File Size Uploaded
polars_hash-0.9.2.tar.gz 99.0 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for polars-hash 0.9.2
File
polars_hash-0.9.2-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
polars_hash-0.9.2-cp310-abi3-win32.whl CPython 3.10 abi3 Windows x86-32 Details
polars_hash-0.9.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
polars_hash-0.9.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
polars_hash-0.9.2-cp310-abi3-manylinux_2_12_i686.manylinux2010_i686.whl CPython 3.10 abi3 Linux glibc 2.12+ x86-32 Details
polars_hash-0.9.2-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details
polars_hash-0.9.2-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details

Total release size: 49.5 MB

Release files / polars_hash-0.9.2.tar.gz

Download URL polars_hash-0.9.2.tar.gz
Size 99.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e80674dc2eff4d72e3c314ea4e3da5aca613d9768f6a81a5c38b876c2042dcd5
BLAKE2b-256 checksum
How to use checksums
c429791f4a2d7014a233359a37e25b7b8f2a2f106091d8c2bb9dbdcb53bc51d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / polars_hash-0.9.2-cp310-abi3-win_amd64.whl

Download URL polars_hash-0.9.2-cp310-abi3-win_amd64.whl
Size 7.5 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
e3c720d633ff6b0132e8059217ea697ffe1c07e9feab6f450b1f5632eb498683
BLAKE2b-256 checksum
How to use checksums
d12a3dfb6fe79ea812858b137c9167ae6383fb129fdf7d27f9ed148da6ff1dd0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / polars_hash-0.9.2-cp310-abi3-win32.whl

Download URL polars_hash-0.9.2-cp310-abi3-win32.whl
Size 6.7 MB
Tags CPython 3.10 Windows x86-32 abi3
SHA-256 checksum
How to use checksums
2da3beac9f5cf1c338fd6a716008c0bdd3e2cc47c6f2371d0c1fa3e5f21cc6af
BLAKE2b-256 checksum
How to use checksums
e5cde087b22f423872d8fd4773060ccac177933068ee8aeb8d018efc15d22725
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / polars_hash-0.9.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL polars_hash-0.9.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 7.3 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
c9225d357eb2c0a6738dbcfc2af1fb0916791b3d1f9dd9954ee5b250788d0d97
BLAKE2b-256 checksum
How to use checksums
45463e283f1a1cd17d527020ebd25241e858d4e50e9ddf06a7707a1743702b36
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / polars_hash-0.9.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL polars_hash-0.9.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 6.6 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
ce11421600aa1873813d03ce667710775655321e513acae59575d310280c5f17
BLAKE2b-256 checksum
How to use checksums
f1f4e07ee12bc7e768c679b25869be6675593d7bf37b6054ad139d7d581d10cf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / polars_hash-0.9.2-cp310-abi3-manylinux_2_12_i686.manylinux2010_i686.whl

Download URL polars_hash-0.9.2-cp310-abi3-manylinux_2_12_i686.manylinux2010_i686.whl
Size 7.9 MB
Tags CPython 3.10 Linux glibc 2.12+ x86-32 abi3
SHA-256 checksum
How to use checksums
62c1bf0ac203a9572afd047f8543f768b5a3bc099bf8ada08018561c2a896d5a
BLAKE2b-256 checksum
How to use checksums
a93b5e7dc831b04f73bb3f50842296446087dbc7e38a143189d556ba80aeb582
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / polars_hash-0.9.2-cp310-abi3-macosx_11_0_arm64.whl

Download URL polars_hash-0.9.2-cp310-abi3-macosx_11_0_arm64.whl
Size 6.3 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
b5001f1ae2a4a9e2013f057c67d4958d73db9d2fdf3ee7080a14b25e4ba0dc69
BLAKE2b-256 checksum
How to use checksums
9f8543004f8ea5051adb80a2d0c9c10e206b891b6fea47df07facfaa8e4503f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / polars_hash-0.9.2-cp310-abi3-macosx_10_12_x86_64.whl

Download URL polars_hash-0.9.2-cp310-abi3-macosx_10_12_x86_64.whl
Size 7.1 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
c27a24b16e040d631f7512948d6e8eafea83b198b3c5d42c448fbe7e0a7e4011
BLAKE2b-256 checksum
How to use checksums
21083829c3dc1d0afdbafa3d353f24527e56b144fa87797176da727c380084e1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0
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