{"id":19946108,"url":"https://github.com/quantco/polarify","last_synced_at":"2025-04-04T22:03:43.300Z","repository":{"id":184828014,"uuid":"672239755","full_name":"Quantco/polarify","owner":"Quantco","description":"Simplifying conditional Polars Expressions with Python 🐍 🐻‍❄️","archived":false,"fork":false,"pushed_at":"2025-03-03T04:11:43.000Z","size":331,"stargazers_count":111,"open_issues_count":11,"forks_count":3,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-03-28T21:03:26.633Z","etag":null,"topics":["ast","machine-learning","polars","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Quantco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-29T11:50:38.000Z","updated_at":"2025-03-22T13:50:57.000Z","dependencies_parsed_at":"2024-02-04T11:41:29.560Z","dependency_job_id":"1acbd20b-b96b-4d77-9c3d-dd58f92bef0f","html_url":"https://github.com/Quantco/polarify","commit_stats":null,"previous_names":["quantco/polarify"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quantco%2Fpolarify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quantco%2Fpolarify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quantco%2Fpolarify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Quantco%2Fpolarify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Quantco","download_url":"https://codeload.github.com/Quantco/polarify/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247256105,"owners_count":20909240,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ast","machine-learning","polars","python"],"created_at":"2024-11-13T00:28:20.361Z","updated_at":"2025-04-04T22:03:43.280Z","avatar_url":"https://github.com/Quantco.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# polarIFy: Simplifying conditional Polars Expressions with Python 🐍 🐻‍❄️\n\n![License][license-badge]\n[![Build Status][build-badge]][build]\n[![conda-forge][conda-forge-badge]][conda-forge]\n[![pypi-version][pypi-badge]][pypi]\n[![python-version][python-version-badge]][pypi]\n[![codecov][codecov-badge]][codecov]\n\n[license-badge]: https://img.shields.io/github/license/quantco/polarify?style=flat-square\n[build-badge]: https://img.shields.io/github/actions/workflow/status/quantco/polarify/ci.yml?style=flat-square\u0026branch=main\n[build]: https://github.com/quantco/polarify/actions/\n[conda-forge]: https://prefix.dev/channels/conda-forge/packages/polarify\n[conda-forge-badge]: https://img.shields.io/conda/pn/conda-forge/polarify?style=flat-square\u0026logoColor=white\u0026logo=conda-forge\n[pypi]: https://pypi.org/project/polarify\n[pypi-badge]: https://img.shields.io/pypi/v/polarify.svg?style=flat-square\u0026logo=pypi\u0026logoColor=white\n[python-version-badge]: https://img.shields.io/pypi/pyversions/polarify?style=flat-square\u0026logoColor=white\u0026logo=python\n[codecov-badge]: https://img.shields.io/codecov/c/github/quantco/polarify?style=flat-square\u0026logo=codecov\n[codecov]: https://codecov.io/gh/quantco/polarify\n\nWelcome to **polarIFy**, a Python function decorator that simplifies the way you write logical statements for Polars. With polarIFy, you can use Python's language structures like `if / elif / else` statements and transform them into `pl.when(..).then(..).otherwise(..)` statements. This makes your code more readable and less cumbersome to write. 🎉\n\n## 🎯 Usage\n\npolarIFy can automatically transform Python functions using `if / elif / else` statements into Polars expressions.\n\n### Basic Transformation\n\nHere's an example:\n\n```python\n@polarify\ndef signum(x: pl.Expr) -\u003e pl.Expr:\n    s = 0\n    if x \u003e 0:\n        s = 1\n    elif x \u003c 0:\n        s = -1\n    return s\n```\n\nThis gets transformed into:\n\n```python\ndef signum(x: pl.Expr) -\u003e pl.Expr:\n    return pl.when(x \u003e 0).then(1).otherwise(pl.when(x \u003c 0).then(-1).otherwise(0))\n```\n\n### Handling Multiple Statements\n\npolarIFy can also handle multiple statements like:\n\n```python\n@polarify\ndef multiple_if_statement(x: pl.Expr) -\u003e pl.Expr:\n    a = 1 if x \u003e 0 else 5\n    b = 2 if x \u003c 0 else 2\n    return a + b\n```\n\nwhich becomes:\n\n```python\ndef multiple_if_statement(x):\n    return pl.when(x \u003e 0).then(1).otherwise(5) + pl.when(x \u003c 0).then(2).otherwise(2)\n```\n\n### Handling Nested Statements\n\nAdditionally, it can handle nested statements:\n\n```python\n@polarify\ndef nested_if_else(x: pl.Expr) -\u003e pl.Expr:\n    if x \u003e 0:\n        if x \u003e 1:\n            s = 2\n        else:\n            s = 1\n    elif x \u003c 0:\n        s = -1\n    else:\n        s = 0\n    return s\n```\n\nwhich becomes:\n\n```python\ndef nested_if_else(x: pl.Expr) -\u003e pl.Expr:\n    return pl.when(x \u003e 0).then(pl.when(x \u003e 1).then(2).otherwise(1)).otherwise(pl.when(x \u003c 0).then(-1).otherwise(0))\n```\n\nSo you can still write readable row-wise python code while the `@polarify` decorator transforms it into a function that works with efficient polars expressions.\n\n### Using a `polarify`d function\n\n```python\nimport polars as pl\nfrom polarify import polarify\n\n@polarify\ndef complicated_operation(x: pl.Expr) -\u003e pl.Expr:\n    k = 0\n    c = 2\n    if x \u003e 0:\n        k = 1\n        c = 0\n        if x \u003c 10:\n            c = 1\n    elif x \u003c 0:\n        k = -1\n    return k * c\n\n\ndf = pl.DataFrame({\"x\": [-1, 1, 5, 10]})\nresult = df.select(pl.col(\"x\"), complicated_operation(pl.col(\"x\")))\nprint(result)\n# shape: (4, 2)\n# ┌─────┬─────────┐\n# │ x   ┆ literal │\n# │ --- ┆ ---     │\n# │ i64 ┆ i32     │\n# ╞═════╪═════════╡\n# │ -1  ┆ -2      │\n# │ 1   ┆ 1       │\n# │ 5   ┆ 1       │\n# │ 10  ┆ 0       │\n# └─────┴─────────┘\n```\n\n### Displaying the transpiled polars expression\n\nYou can also display the transpiled polars expression by calling the `transform_func_to_new_source` method:\n\n```python\nfrom polarify import transform_func_to_new_source\n\ndef signum(x):\n    s = 0\n    if x \u003e 0:\n        s = 1\n    elif x \u003c 0:\n        s = -1\n    return s\n\n\nprint(f\"Original function:\\n{inspect.getsource(signum)}\")\n# Original function:\n# def signum(x):\n#     s = 0\n#     if x \u003e 0:\n#         s = 1\n#     elif x \u003c 0:\n#         s = -1\n#     return s\nprint(f\"Transformed function:\\n{transform_func_to_new_source(signum)}\")\n# Transformed function:\n# def signum_polarified(x):\n#     import polars as pl\n#     return pl.when(x \u003e 0).then(1).otherwise(pl.when(x \u003c 0).then(-1).otherwise(0))\n```\n\nTODO: complicated example with nested functions\n\n## ⚙️ How It Works\n\npolarIFy achieves this by parsing the AST (Abstract Syntax Tree) of the function and transforming the body into a Polars expression by inlining the different branches.\nTo get a more detailed understanding of what's happening under the hood, check out our [blog post](https://tech.quantco.com/blog/polarify) explaining how polarify works!\n\n## 💿 Installation\n\n### conda\n\n```bash\nconda install -c conda-forge polarify\n# or micromamba\nmicromamba install -c conda-forge polarify\n# or pixi\npixi add polarify\n```\n\n### pip\n\n```bash\npip install polarify\n```\n\n## ⚠️ Limitations\n\npolarIFy is still in an early stage of development and doesn't support the full Python language. Here's a list of the currently supported and unsupported operations:\n\n### Supported operations\n\n- `if / else / elif` statements\n- binary operations (like `+`, `==`, `\u003e`, `\u0026`, `|`, ...)\n- unary operations (like `~`, `-`, `not`, ...) (TODO)\n- assignments (like `x = 1`)\n- polars expressions (like `pl.col(\"x\")`, TODO)\n- side-effect free functions that return a polars expression (can be generated by `@polarify`) (TODO)\n- `match` statements\n\n### Unsupported operations\n\n- `for` loops\n- `while` loops\n- `break` statements\n- `:=` walrus operator\n- dictionary mappings in `match` statements\n- list matching in `match` statements\n- star patterns in `match statements\n- functions with side-effects (`print`, `pl.write_csv`, ...)\n\n## 🚀 Benchmarks\n\nTODO: Add some benchmarks\n\n## 📥 Development installation\n\n```bash\npixi install\npixi run postinstall\npixi run test\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquantco%2Fpolarify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquantco%2Fpolarify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquantco%2Fpolarify/lists"}