Skip to main content

polars-map

build pypi

Polars plugin providing a Map extension type stored as List(Struct({key, value})).

Deprecated — Polars 2.0 ships a native pl.Map and reserves the .map namespace, so this package is pinned to polars<2 and emits a DeprecationWarning on import. Its semantics match the native type; see Migrating to native pl.Map.

The type-preserving methods (filter, filter_keys, filter_values, merge, intersection, difference) require a Map input so they can keep its dtype instead of inferring it; the accessors also accept the raw List(Struct).

Installation

pip install polars-map

Supported operations (.map.*)

Category Methods
Accessors entries, keys, values, len, get, contains_key
Filtering filter, filter_keys, filter_values
Transform eval, eval_keys, eval_values
Set ops merge, intersection, difference
Conversion from_entries
Iteration __iter__, to_list (Series only)

Arrow conversion

Function Description
from_arrow(table) Arrow Table/RecordBatch to Polars DataFrame, preserving map<> as Map
from_arrow_array(array) Arrow Array to Polars Series, preserving map<> as Map
to_arrow(frame) Polars DataFrame to Arrow Table, converting Map back to map<>
to_arrow_array(series) Polars Series to Arrow Array, converting Map back to map<>
scan_arrow(source) Lazy scan from an Arrow source with Map preservation

Usage

import polars as pl
import pyarrow as pa
from polars_map import Map, from_arrow, to_arrow, scan_arrow

ser = pl.Series(
    "m",
    [
        [{"key": "a", "value": 1}, {"key": "b", "value": 2}],
        [{"key": "x", "value": 10}],
    ],
    dtype=Map(pl.String(), pl.Int64()),
)
df = pl.DataFrame([ser])

# accessors
df.select(pl.col("m").map.keys())  # [["a", "b"], ["x"]]
df.select(pl.col("m").map.values())  # [[1, 2], [10]]
df.select(pl.col("m").map.len())  # [2, 1]

# lookup
df.select(pl.col("m").map.get("a"))  # [1, None]
df.select(pl.col("m").map.contains_key("a"))  # [True, False]

# filtering
df.select(pl.col("m").map.filter(pl.element().struct["value"] > 1))
df.select(pl.col("m").map.filter_keys(pl.element() > "a"))
df.select(pl.col("m").map.filter_values(pl.element() >= 2))

# transform keys or values
df.select(pl.col("m").map.eval_keys(pl.element().str.to_uppercase()))
df.select(pl.col("m").map.eval_values(pl.element() * 2))

# merge: right value, left position
left = pl.Series(
    "l",
    [[{"key": "a", "value": 1}, {"key": "b", "value": 2}]],
    dtype=Map(pl.String(), pl.Int64()),
)
right = pl.Series(
    "r",
    [[{"key": "a", "value": 99}, {"key": "c", "value": 3}]],
    dtype=Map(pl.String(), pl.Int64()),
)
pair = pl.DataFrame([left, right])
pair.select(pl.col("l").map.merge(pl.col("r")))
# [{"a": 99, "b": 2, "c": 3}]

# set operations
pair.select(pl.col("l").map.intersection(pl.col("r")))  # keys in both
pair.select(pl.col("l").map.difference(pl.col("r")))  # keys only in left

# strip Map -> List(Struct)
df.select(pl.col("m").map.entries())

# from_entries is the inverse
entries = pl.Series(
    "e",
    [[{"key": "a", "value": 1}, {"key": "b", "value": 2}, {"key": "a", "value": 3}]],
    dtype=pl.List(pl.Struct({"key": pl.String, "value": pl.Int64})),
)
pl.DataFrame([entries]).select(pl.col("e").map.from_entries())  # {"a": 3, "b": 2}

# Series iteration yields dicts
for d in ser.map:
    print(d)  # {"a": 1, "b": 2}, {"x": 10}

# arrow roundtrip
table = pa.table({"m": pa.array([[("a", 1)]], type=pa.map_(pa.string(), pa.int64()))})
df = from_arrow(table)  # Map(String, Int64) dtype preserved
table2 = to_arrow(df)

# lazy scanning from an arrow source
lf = scan_arrow(lambda: [table])
result = lf.collect()

Caveats

  • Extension types — used to wrap the underlying List(Struct) storage with a semantic Map dtype, are not yet stabilized and may change across Polars releases.
  • pl.dtype_of — used to efficiently cast to the extension type after some operations is also unstable.
  • GIL - is required to automatically wrap an expression as the extension type, and so operations which could change the underlying key or value types will briefly lock the GIL to do the cast. This may also prevent the polars engine from reasoning about the type.
  • Large offsets — Arrow's map<> type uses only 32-bit offsets, so exporting a Polars map backed by a LargeList whose offsets don't fit in a u32 will error. Arrow has no large-offset map type.

Migrating to native pl.Map

Map(pl.String(), pl.Int64()) becomes pl.Map(pl.String, pl.Int64), .map.from_entries() becomes .list.to_map(), and the Arrow helpers become pl.from_arrow / .to_arrow().

The remaining methods have no native counterpart; write them as .map.entries(), a list.eval, and .list.to_map() when a map is rebuilt.

m.map.entries().list.eval(pl.element().struct["key"])  # keys
pl.concat_list(l.map.entries(), r.map.entries()).list.to_map()  # merge

Metadata

Release files for polars-map 0.3.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 polars-map 0.3.0
File Size Uploaded
polars_map-0.3.0.tar.gz 73.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for polars-map 0.3.0
File Interpreter ABI Platform
polars_map-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 87.1 kB

Release files / polars_map-0.3.0.tar.gz

Download URL polars_map-0.3.0.tar.gz
Size 73.0 kB
Tags Source
SHA-256 checksum
How to use checksums
ff4d6490f619fc094dc32c5ee74cf73db393b13b2282c18960f7d283d6939d24
BLAKE2b-256 checksum
How to use checksums
4e4229682383b98c0fa631b0f29a27f25d51df5abf1e5509bd77991489bc437d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release files / polars_map-0.3.0-py3-none-any.whl

Download URL polars_map-0.3.0-py3-none-any.whl
Size 14.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7f6dfb79d3ddab7e733a5f2dcf878b7f618caa5191b80c0f32ad742d5045bd35
BLAKE2b-256 checksum
How to use checksums
1b63d1d11e789e8111e2f0fe0c1bfd2d0ed33aa3a9ae65884fd449da1b5e0f24
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

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