Skip to content

Conversation

Excidion
Copy link

@Excidion Excidion commented Jun 22, 2025

What type of PR is this? (check all applicable)

  • πŸ’Ύ Refactor
  • ✨ Feature
  • πŸ› Bug Fix
  • πŸ”§ Optimization
  • πŸ“ Documentation
  • βœ… Test
  • 🐳 Other

Related issues

Checklist

  • Code follows style guide (ruff)
  • Tests added
  • Documented the changes

If you have comments or can explain your changes, please do so below

Adds ability to register new namespaces like so (I was surprised narwhals didn't have ceil and floor yet):

import narwhals as nw
import pandas as pd

@nw.api.register_expr_namespace("rounding")
class Rounding:
    def __init__(self, expr: nw.Expr) -> None:
        self._expr = expr

    def ceil(self, dtype=nw.Int64) -> nw.Expr:
        return (self._expr + 1).cast(dtype=dtype)   # i know this doesn't actually work for all cases

    def floor(self, dtype=nw.Int64) -> nw.Expr:
        return self._expr.cast(dtype=dtype)


df = nw.from_native(pd.DataFrame([1.4, 24.3, 55.7, 64.001], columns=["n"]))
print(df.select(
    nw.col("n"),
    nw.col("n").rounding.floor().alias("floor"),
    nw.col("n").rounding.ceil().alias("ceil"),
).to_native().to_markdown())
"""
|    |      n |   floor |   ceil |
|---:|-------:|--------:|-------:|
|  0 |  1.4   |       1 |      2 |
|  1 | 24.3   |      24 |     25 |
|  2 | 55     |      55 |     56 |
|  3 | 64.001 |      64 |     65 |
"""

Heavily "inspired" by the polars implementation. Still needs tests and also updates to the docstrings. Just wanted to know if this is even going in the right direction before proceeding?

Checklist:

  • Tested for Expr
  • Tested for Series ?
  • Tested for DataFrame ?
  • Tested for LazyFrame ?

This is my first time contributing to FOSS, so please forgive if I missed anything. :)

@Excidion Excidion marked this pull request as draft June 22, 2025 12:59
@Excidion Excidion changed the title Custom namespace registration feat: Custom namespace registration Jun 22, 2025
@MarcoGorelli
Copy link
Member

thanks for the pr!

it's not clear to me why this is needed - could you clarify why this is more desirable than just

import narwhals as nw
import pandas as pd

def ceil(expr, dtype=nw.Int64) -> nw.Expr:
    return (expr + 1).cast(dtype=dtype)

def floor(expr, dtype=nw.Int64) -> nw.Expr:
    return expr.cast(dtype=dtype)


df = nw.from_native(pd.DataFrame([1.4, 24.3, 55.7, 64.001], columns=["n"]))
print(df.select(
    nw.col("n"),
    floor(nw.col("n")).alias("floor"),
    ceil(nw.col("n")).alias("ceil"),
).to_native().to_markdown())

please?

@Excidion
Copy link
Author

Excidion commented Jun 24, 2025

Sure! So the original starting point is my wish to use narwhals as a backend for featuretools.

I looked into the featuretools code and found out that it heavily relies on woodwork for it's logic. So as I understand it, the first step would have to be, to narwhalify woodworks WoodworkTableAccessor class.

For now, woodwork only supports pandas and registers itself to a pd.DataFrame's Namspace like that:

# woodwork/woodwork/table_accessor.py
@pd.api.extensions.register_dataframe_accessor("ww")
class PandasTableAccessor(WoodworkTableAccessor):
    pass

Therefore my idea was, that if narwhals had a similar capability, we could add something like this:

# woodwork/woodwork/table_accessor.py
@nw.api.register_dataframe_accessor("ww")
class NarwhalsTableAccessor(WoodworkTableAccessor):
    pass  # TODO

Therefore I looked into the polars repo to see how it's implemented there as inspiration. The result is this PR.
(In the meantime I also tested the nw.api.register_dataframe_accessor function with positive results.)

Hope this gives a bit better context. Love to hear your thoughts if you think this could benefit narwhals generally.

@Excidion
Copy link
Author

Excidion commented Jul 2, 2025

@MarcoGorelli if you think this is not within scope (maybe also related to #267) let me know, then I'll investigate other options between woodwork and narwhals :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants