Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: explain translation from narwhals api to native api #684

Merged
merged 6 commits into from
Jul 31, 2024

Conversation

amol-
Copy link
Contributor

@amol- amol- commented Jul 30, 2024

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

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

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

The current documentation is unclear about the how objects move from narwhals api to polars compatible backend to native api. This adds a section that tries to make that more clear.

@github-actions github-actions bot added the documentation Improvements or additions to documentation label Jul 30, 2024
@MarcoGorelli
Copy link
Member

thanks @amol- , amazing stuff here! I've just reworded it a bit, and will try to do a bit more tomorrow, but I think this is super-important to be documented, so thanks a tonne for having started it πŸ™

@amol-
Copy link
Contributor Author

amol- commented Jul 31, 2024

@MarcoGorelli I think that in the rewording we lost a little bit the message that the last part tried to convey.
In the last paragraph I was trying to explain and showcase how narwhals.Dataframe and PandasLikeDataframe can be used interchangeably in the narwhals api and that thus even if methods return the "Like" version the user doesn't have to care about that.

I'm referring to this part:

After a compliant object is returned, the user will keep using and perform
additional operations on the compliant object itself, as the compliant
object implements the same API as the narwhals objects and is accepted
as an argument by all narwhals functions.

For example nw.col("b")._call(nwdf.__narwhals_namespace__()) on a
pyarrow.Table will return an ArrowExpr:

  ArrowExpr(depth=0, function_name=col, root_names=['b'], output_names=['b']

but invoking narwhals.Dataframe.select on it will work and return
a new narwhals.Dataframe as if we passed a narwhals.Expr itself:

>>> nwexpr = nw.col("b")
>>> type(nwexpr)
<class 'narwhals.stable.v1.Expr'>
>>> nwr = nwdf.select(nw.col("b"))
>>> type(nwr)
<class 'narwhals.stable.v1.DataFrame'>
>>> arrowexpr = nw.col("b")._call(nwdf.__narwhals_namespace__())
>>> type(arrowexpr)
<class 'narwhals._arrow.expr.ArrowExpr'>
>>> nwr = nwdf.select(arrowexpr)
>>> type(nwr)
<class 'narwhals.stable.v1.DataFrame'>

@MarcoGorelli
Copy link
Member

Thanks - I'll double check but I'm not sure it's intentional that that's supported

@MarcoGorelli
Copy link
Member

In fact, I just applied the following diff, ran the test suite, and no test failed:

diff --git a/narwhals/dataframe.py b/narwhals/dataframe.py
index 644db7bc..07c567bd 100644
--- a/narwhals/dataframe.py
+++ b/narwhals/dataframe.py
@@ -123,6 +123,9 @@ class BaseFrame(Generic[FrameT]):
         *exprs: IntoExpr | Iterable[IntoExpr],
         **named_exprs: IntoExpr,
     ) -> Self:
+        from narwhals._pandas_like.expr import PandasLikeExpr
+        if any(isinstance(x, PandasLikeExpr) for x in exprs):
+            1/0

Passing a compliant Expr to nw.DataFrame.select doesn't happen internally, and it's not something users are meant to do - could you clarify why it needs mentioning please? I might be missing something though, so sorry if that's the case πŸ™

@amol-
Copy link
Contributor Author

amol- commented Jul 31, 2024

In fact, I just applied the following diff, ran the test suite, and no test failed:

diff --git a/narwhals/dataframe.py b/narwhals/dataframe.py
index 644db7bc..07c567bd 100644
--- a/narwhals/dataframe.py
+++ b/narwhals/dataframe.py
@@ -123,6 +123,9 @@ class BaseFrame(Generic[FrameT]):
         *exprs: IntoExpr | Iterable[IntoExpr],
         **named_exprs: IntoExpr,
     ) -> Self:
+        from narwhals._pandas_like.expr import PandasLikeExpr
+        if any(isinstance(x, PandasLikeExpr) for x in exprs):
+            1/0

Passing a compliant Expr to nw.DataFrame.select doesn't happen internally, and it's not something users are meant to do - could you clarify why it needs mentioning please? I might be missing something though, so sorry if that's the case πŸ™

Ah good to know, I thought that the interoperability was by design. So every API always should invoke _from_compliant_dataframe (or equivalent) to surface to users only the narwhals.* objects? It might make sense to document that.

@MarcoGorelli
Copy link
Member

Yup! I think the type hints usually make that clear? Most methods return Self

Anyway, thanks for your PR, let's ship this

Copy link
Member

@MarcoGorelli MarcoGorelli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @amol- !

@MarcoGorelli MarcoGorelli merged commit e45fa4a into narwhals-dev:main Jul 31, 2024
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants