Skip to main content

unloop

Turn slow pandas loops into fast, verified vectorized code.

unloop finds slow patterns in your pandas and NumPy code, like iterrows() loops and apply(axis=1), and rewrites them into fast vectorized operations. Every rewrite is run and compared against your original code before it's offered, so unloop only ever makes your code faster, never different.

%%unloop
for i, row in df.iterrows():
    df.at[i, "total"] = row["price"] * row["qty"]
unloop: 2016x faster via rules, results identical. Running:
df['total'] = df['price'] * df['qty']

Why unloop?

Row-by-row loops are one of the most common reasons pandas code is slow. Rewriting them by hand is easy to get subtly wrong, especially with missing values and data types. unloop does the rewrite for you and proves it's correct on your actual data.

  • Verified, not guessed. Both versions run on private copies of your data, plus extra test data with missing values mixed in. If the results differ in any way, the rewrite is rejected.
  • Only when it's actually faster. Every rewrite is benchmarked, and unloop only changes your code if it's at least 1.5x faster.
  • Your data stays untouched. Verification and timing run on copies, never on your real variables.
  • Keeps your formatting. Only the slow lines change; your comments and blank lines stay exactly as you wrote them.
  • Private by design. The optional AI runs on your own computer through Ollama. Nothing is sent to the cloud.

Installation

pip install unloop

Requires Python 3.9+ and pandas 2.0+.

Optional: for faster text operations, also install PyArrow:

pip install pyarrow

Quick start

In Jupyter notebooks

Load the extension once per notebook:

%load_ext unloop

Then put %%unloop at the top of any cell:

%%unloop
df["total"] = df.apply(lambda r: r["price"] * r["qty"], axis=1)

What happens next depends on what unloop finds:

Result What unloop does
Faster, results identical Runs the fast version and shows you the new code
Faster, but data types change Runs your original code and shows the faster version as a suggestion
No safe speedup found Runs your original code unchanged

To skip the AI and use only the built-in rules:

%%unloop --no-ai

In Python code

import unloop

result = unloop.optimize(code, {"df": df})

print(result["status"])   # "optimized", "no_change", "rejected", or "not_faster"
print(result["code"])     # the optimized code, or your original if not optimized

What unloop can rewrite

Slow pattern Becomes
for i, row in df.iterrows(): df.at[i, "c"] = row["a"] * row["b"] df["c"] = df["a"] * df["b"]
df["c"] = df.apply(lambda r: r["a"] * r["b"], axis=1) df["c"] = df["a"] * df["b"]
df["c"] = df["s"].apply(lambda x: x.strip()) df["c"] = df["s"].str.strip()
df["c"] = df["k"].apply(lambda x: lookup[x]) df["c"] = df["k"].map(lookup)
for x in items: out = pd.concat([out, piece]) out = pd.concat([out] + [piece for x in items])

Code that doesn't match these rules can be handled by the optional AI fallback.

Optional: AI fallback with Ollama

For slow code that none of the built-in rules recognize, unloop can ask a small coding model running locally on your computer.

  1. Install Ollama from ollama.com.

  2. Download the model:

    ollama pull qwen2.5-coder:3b
    

That's it. unloop uses it automatically when Ollama is running. AI suggestions go through exactly the same verification and benchmarking as the built-in rules, and if a suggestion fails, unloop tells the AI what went wrong and lets it try again (up to 3 times).

Verified AI rewrites are saved in ~/.unloop/cache.json on your computer, so the same code never needs the AI twice. Saved rewrites are re-verified on your current data every time they're used.

How it stays safe

For every rewrite, unloop:

  1. Runs your original code and the new code on separate private copies of your data.
  2. Compares every resulting DataFrame: values, columns, index, and data types.
  3. Repeats the comparison on a small copy of your data with missing values (NaN) inserted, to catch bugs your current data might not reveal.
  4. Benchmarks both versions and keeps the new code only if it's meaningfully faster.

If anything fails, your original code is used.

Limitations

  • unloop compares DataFrames. Changes to other kinds of variables (lists, dictionaries, files written to disk) are not checked.
  • Verification runs both versions of your code. Avoid using %%unloop on cells with side effects like writing files, sending emails, or calling external APIs.
  • AI-generated code is run on copies of your data during verification. It comes from a model on your own machine, but as with any generated code, review it before relying on it in important work.
  • The verification is thorough but not a mathematical proof. It tests your data and common edge cases, not every possible input.

License

MIT License. Copyright (c) 2026 Sankalp Gaur. See LICENSE for details.

Metadata

Release files for unloop 1.0.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 unloop 1.0.0
File Size Uploaded Provenance Actions
unloop-1.0.0.tar.gz 15.0 kB Without provenance Details for unloop-1.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for unloop 1.0.0
File Interpreter ABI Platform Actions
unloop-1.0.0-py3-none-any.whl Python 3 none any Details for unloop-1.0.0-py3-none-any.whl

Total release size: 28.6 kB

Release files / unloop-1.0.0.tar.gz

Download URL unloop-1.0.0.tar.gz
Size 15.0 kB
Tags Source
SHA-256 checksum
How to use checksums
3b00574d4610b0d3829b8b9029f478e20948040dc04328ca7e8da3e3c7e4cdce
BLAKE2b-256 checksum
How to use checksums
1bdc15a4ac45268fe459d2b52b47d00f471f64711471cf99367b76e79c17ba06
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.9

Release files / unloop-1.0.0-py3-none-any.whl

Download URL unloop-1.0.0-py3-none-any.whl
Size 13.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4ea8560f172a0ed2f5a9c082d70ebb42837bbf724d96fe409be9676a82975bd9
BLAKE2b-256 checksum
How to use checksums
30bd9b5e4816694611d81ebb15c9c5eff911fdaa819fb71f079ff0a549726ae2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.9

Security for unloop 1.0.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files No provenance

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