Native LUT remapping for large Pandas categorical code buffers
Project description
zh_catmut
Remap huge Pandas categorical columns without expanding them into object arrays or allocating boolean masks.
Before / After
# Before: high-level remapping can allocate temporary arrays or trigger
# categorical re-encoding work on the full column.
series = series.cat.rename_categories({"pending": "active"})
series = series.cat.set_categories(["active", "disabled"])
# After: build a dense metadata LUT, mutate integer categorical codes natively,
# and return a refreshed categorical object.
from zh_catmut import remap_categorical
series = remap_categorical(
series,
{"pending": "active", "disabled_old": "disabled"},
copy_fallback=True,
)
Installation
For released wheels:
pip install zh-catmut
For a source checkout:
python -m pip install .
Verify the installed wheel and bundled native library:
zh-catmut doctor
The import package name uses an underscore:
import zh_catmut
Quickstart
import pandas as pd
from zh_catmut import remap_categorical
s = pd.Series(pd.Categorical(["new", "old", "old", None]))
out = remap_categorical(s, {"old": "new"}, copy_fallback=True)
copy_fallback=True is the safest default for application code because it allocates a Python-owned destination codes buffer and keeps the original object unchanged.
Why it's fast
- Pandas categoricals store the full column as dense integer
codes; category labels are only metadata. zh_catmutbuilds a small denseint64lookup table from category labels in Python.- A bundled Zig shared library receives only raw pointers, lengths, primitive flags, and POD reports through a C ABI.
- The native loop remaps contiguous
int8,int16,int32, orint64code buffers in one batch. ctypes.CDLLis used so the GIL is released while the native remap executes.- Python runs shape, dtype, contiguity, writeability, and Copy-on-Write safety gates before exporting pointers.
- Native validation is all-or-nothing: invalid source codes, invalid target codes, null pointers, and oversized lengths are rejected before mutation.
- If in-place mutation is unsafe,
copy_fallback=Trueuses a Python-owned destination buffer and keeps the source buffer unchanged.
Public API
from zh_catmut import remap_categorical, remap_codes_inplace
Use remap_categorical for Pandas objects and remap_codes_inplace only when you already own a writable, contiguous NumPy codes buffer and a dense int64 LUT.
remap_categorical
remap_categorical(
obj,
mapping,
*,
assume_unique=False,
copy_fallback=False,
threads=0,
)
obj: a PandasSerieswith categorical dtype or apd.Categorical.mapping: mapping from old labels to new labels. Labels not present in the mapping are preserved.copy_fallback: whenTrue, allocate a destination codes buffer and avoid in-place ownership risk.assume_unique: expert-only escape hatch for controlled in-place mutation after all other gates pass.threads: reserved for future native parallelism. The current V1 kernel accepts0or1and uses the scalar remap path.
remap_codes_inplace
remap_codes_inplace(
codes,
lut,
*,
target_category_count,
missing_code=-1,
allow_missing=True,
threads=0,
)
codes: one-dimensional, C-contiguous NumPy array with dtypeint8,int16,int32, orint64.lut: one-dimensional, C-contiguousnp.int64lookup table.target_category_count: every mapped non-missing code must be in[0, target_category_count).missing_code: default-1, matching Pandas categorical codes.allow_missing: whenFalse, missing input or missing LUT output is rejected before mutation.
Command-line help for installed users
zh-catmut installs a small diagnostic CLI:
zh-catmut --help
zh-catmut info
zh-catmut example
zh-catmut doctor
python -m zh_catmut doctor
infoprints the project purpose, install command, API summary, and support links.exampleprints a minimalcopy_fallback=TruePandas example.doctorverifies NumPy/Pandas imports, native library loading, ABI version, and low/high-level remap smoke tests.- If your Python user scripts directory is not on
PATH, usepython -m zh_catmut ...instead ofzh-catmut ....
Testing and native transparency
The native implementation is tracked in native/src/root.zig, with the C ABI declared in include/zh_catmut_abi.h. Tests are included so the compiled shared library is not a black-box artifact:
python -m pip install -e ".[test]"
python -m pytest -q
cd native && zig build test
The Python tests load the packaged native library, verify the ABI, exercise every supported integer code dtype, check all-or-nothing validation, run the Pandas copy-fallback path, and execute python -m zh_catmut doctor.
Troubleshooting
NativeLibraryLoadError
Run:
zh-catmut doctor
If the package was installed from a wheel, reinstall:
python -m pip install --force-reinstall zh-catmut
If pip built from source, Zig must be installed and visible as zig on PATH, or set:
ZIG=/path/to/zig python -m pip install zh-catmut
Copy-on-Write safety errors
For ordinary Pandas application code, prefer:
out = remap_categorical(series, mapping, copy_fallback=True)
Use assume_unique=True only when you control the object lifetime and know the underlying categorical codes buffer is not shared.
Supported runtime inputs
- Python 3.9+
- CPython
- NumPy + Pandas
- Pandas categorical codes backed by contiguous signed integer arrays
- Code dtypes:
int8,int16,int32,int64
Links
- GitHub profile: mohamedhossammohamed
- X profile: @MohamedHz72007
- License: Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zh_catmut-0.1.0.tar.gz.
File metadata
- Download URL: zh_catmut-0.1.0.tar.gz
- Upload date:
- Size: 23.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0255a02cb7e8041fb38c5bdc2338a392bd8d7a04548bf4b771e3730ab484fa3a
|
|
| MD5 |
d8f81562d34fe9c02e252b1cf209c367
|
|
| BLAKE2b-256 |
283f677ee473b5b83fec885a69352c32c27839f7716ef6d1b6edce325483b192
|
File details
Details for the file zh_catmut-0.1.0-cp39-cp39-macosx_11_0_arm64.whl.
File metadata
- Download URL: zh_catmut-0.1.0-cp39-cp39-macosx_11_0_arm64.whl
- Upload date:
- Size: 20.7 kB
- Tags: CPython 3.9, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fb5a0a8fd85815f6b8f672207a8230fdfc17150e9c48d146949530ba8dd6f6c
|
|
| MD5 |
6f4ae80e596f277bbbf84b28a4d58dff
|
|
| BLAKE2b-256 |
88de4f186a041bfaea90bee5dd4ca0e48dff90123754d09a4d302dfb6e78fb50
|