From 6d05830bcd10fe8d1597942fe8879d9d520c0240 Mon Sep 17 00:00:00 2001 From: eyrei123 Date: Thu, 6 Nov 2025 20:02:54 +0000 Subject: [PATCH 1/8] Initial Commit --- narwhals-python/README.md | 20 +++++++++ narwhals-python/authors.parquet | Bin 0 -> 2797 bytes narwhals-python/books.parquet | Bin 0 -> 4234 bytes narwhals-python/exercise_solution.py | 12 +++++ narwhals-python/presidents.parquet | Bin 0 -> 3404 bytes narwhals-python/universal_processing.py | 57 ++++++++++++++++++++++++ 6 files changed, 89 insertions(+) create mode 100644 narwhals-python/README.md create mode 100644 narwhals-python/authors.parquet create mode 100644 narwhals-python/books.parquet create mode 100644 narwhals-python/exercise_solution.py create mode 100644 narwhals-python/presidents.parquet create mode 100644 narwhals-python/universal_processing.py diff --git a/narwhals-python/README.md b/narwhals-python/README.md new file mode 100644 index 0000000000..ceb2a03db9 --- /dev/null +++ b/narwhals-python/README.md @@ -0,0 +1,20 @@ +This file contains the downloadable code from the RealPython tutorial: \[Writing DataFrame Agnostic Python Code With Narwhals](https://realpython.com/dataframe-agnostic-code-with-narwhals-python/) + + + +authors.parquet - File of data for main sections of the tutorial. + +books.parquet - File of data for the self study section of the tutorial. + +presidents.parquet - File of data for the self study section of the tutorial. + + + +exercise\_solution.py - File containing a possible solution to the self study exercise. + +universal\_processing.py - File containing functions used in the main sections of the tutorial. + + + + + diff --git a/narwhals-python/authors.parquet b/narwhals-python/authors.parquet new file mode 100644 index 0000000000000000000000000000000000000000..e9d4cc7a43706f9e51b5bdea3b1f73df38e3502e GIT binary patch literal 2797 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 literal 0 HcmV?d00001 diff --git a/narwhals-python/exercise_solution.py b/narwhals-python/exercise_solution.py new file mode 100644 index 0000000000..d07955980b --- /dev/null +++ b/narwhals-python/exercise_solution.py @@ -0,0 +1,12 @@ +import narwhals as nw +from narwhals.typing import IntoFrameT + + +def rowling_books(df: IntoFrameT, lf: IntoFrameT) -> IntoFrameT: + return ( + nw.from_native(df) + .join(nw.from_native(lf).filter(nw.col("last_name").str.contains("Rowling")).collect(), on="author_id") + .select(["book_title", "year_published", "first_name", "last_name"]) + .sort("year_published") + .to_pandas() + ) diff --git a/narwhals-python/presidents.parquet b/narwhals-python/presidents.parquet new file mode 100644 index 0000000000000000000000000000000000000000..13279555b5fe28b99438ccd8c2892f071796b504 GIT binary patch literal 3404 zcmbtX3se(l7M?r|0Rl*6h6E4-Xhh|a@JtX|CSt%4F-Ca^hz=o0gz(6Nh?Y|{`&TXxqqJ2Max_rSX6>>T*#|L^_hyZ3(g z{`Wr-!x9ci2D>R>KUoBdK>z^UTD<412j&iS1%9<)t~TI%mo>$$ zORDYF>u3wKhp5l{OT2R2m&A~QJj3F8ez_IyAJ%$4^?|8+&`xs`t@CxSIFdU@N);gtD@VpVv0A zJE3ZZZ|{c1Ap{TrW5G@CU?Mmhq<|C$f543rBTrXlX3%HB$%sNV$tTktApk^lkw~Ce zgfMBLV!Fv*H}hVumCf=w8u0-QQh9c5!joVpda*0-;A43pNMrZ`l-UfrX*!}(ug^df zGLQx(LM2q_B!xu{n#K^C#xfId?7cKz1@cUR=$rno>;`|6??clXZ;boAv-XpX*mgEt zY)B|@5~$rQ&D_3=e={m^2Rs0Gz`k~MpWVK9wn6?afu27;7&1^A+vE8G0f*Zx^cBY%s` zin&&*19o?Y#yjnjmj>&sO82kWA0bZ+_se@*)XllwY%6(o@#z&(d$ZfKCaNoQ!_lOa zfTF=&J<1n(ceg}8D^0H*-I{s9+_nA|r?~2VE>h{VEruR>w|vpX?*?r=k;55BUebcD z@Pswl)RNx^A0g*z0O2w7SjR87Hxi$cr^%^F93o9cl(}>hI7x}5B8nN(N?Jt^%b(Zj z&0aQ4v$BDELZkY&%kH&n9+>PH3P;oGJ(X6o6uHtkuRT<#gTgv!f+cnuYiMqdn}K6Q z5n5^bBf6K6Hw#d9Skr21EeqG*BftG7r{3aqXQ{lmcKN<{Uh1vShhA^djuriskp1w^ zo_F_kcUo<47W_iK*jDXY<|;WdUh$8nLi4ijiY%{9R01`C8FKj}4STpLr8#AwtBb3$ zOtE+w-+%gsYGcAUH|;^ivZVu#iss#Q_M?jqf31Ci2&C1!D~}EaUUjtMb(@NcH^EP` zc_q>UlamDpEVoHX!-H)c`vTv_M}?%}a_RNIw{zI@r{UJjo9*rA!RB~)v*~7>04~pi z?d##go`K;|#3B5syJ$E_Ja5Gs*}B*|MZ%N34Q^%0^24e1jp?Hw8yHs0l#2B#HKJ7G zC+D>}bc@XDw!|2o(dLXie?-N2<|SWv!y5doWwoM#dtdXsQ#0E4N!O|H9~w4)eY!(y zw@;n(aJ5eQl%om}lZpJcUeO$9c8PmnwLP*|?nr?FDwipC-8GgUQck#Ba;@rS72@MF z+|H{AZX3O{V|(?I;Y(NVzSW^z1k+>asROM)nH`# z5s#mPJa?)-&C1uD?s4Y&pSFy2Y~>t(7#Hb4-^u$;HJl`zfoGIkJW-qOLE?cs-$VsQm zvmO6K{=$gL5i9ZKHFe~}K}ENAdh%94x?cg=&yw1gt_Q5HornBKY>6Zw%%ek|JtE~} zec2Zjyw{h>F{$#6bhA*IB2%hF)N-jla=V+rWNRi_6wOnNbeu~2QKPt%GuqdlS?2>H2W$%_HEPW7i4EPvSUgqy#zHegr5KC#`I(eKi3|ruI_osW zVJd_F`&|#Uxqx(N$O-fXSPv`=2u9xHW$=M(1scF$4l=<&fOT|^5sV>Pqf`BX-U+?N zz-}->0l*rg8^ESGGJ^U*gMdn0F~6KKs7nq8C?jTZun(L;=r{&5;EaV==wyJ=X9CBV z@uWb1b_F5mpbO{;K=<6CL>3jgWM_jFA)N+GBr9VARnk4bQ7=5pT7mHE7R*UJE!|=w*eQVKoC@#bYAtvVI$`#lY{SJMi zFjHaJ46}xRkB$;thpllv9|H)BOi#*?aHJV&uo$zq8Hd6*qJE&yvMBt84!B;MiO%@i zwXs6BESjfT8^cLQ*O~v_-h>{<3zwuz6`Yi~7{4?eSGWfKl#2y5!N5eEd;zXRhY3B( z2Mi~NMdv0(^R^_1338Lswe|!4;`#}H6-cabOR_-kZ>S3MSA>C11c}?n`9b+wwh?s& zd#}QHN7=>(^zp*;u?kb+tS5yDj4*?P0XjvTnT{w`jC8b7{Kp> IntoFrameT: + return ( + nw.from_native(df) + .group_by("party_name") + .agg(nw.col("last_name").count()) + .sort("party_name") + .to_native() + ) + +@nw.narwhalify +def universal_groupby_v2(df: FrameT) -> FrameT: + return ( + df + .group_by("party_name") + .agg(nw.col("last_name").count()) + .sort("party_name") + ) + + +def universal_groupby_v3(df: IntoFrameT) -> IntoFrameT: + return ( + nw.from_native(df) + .group_by("party_name") + .agg(nw.col("last_name").count()) + .sort("party_name") + .to_polars() + ) + + +def universal_pivot_v1(df: IntoFrameT) -> IntoFrameT: + return ( + nw.from_native(df) + .pivot( + on="party_name", + index="century", + aggregate_function="count", + values="last_name" + ).to_native() + ) + + +def universal_pivot_v2(df: IntoFrameT) -> IntoFrameT: + if isinstance(nw.from_native(df), nw.LazyFrame): + df = nw.from_native(df).collect() + return ( + nw.from_native(df) + .pivot( + on="party_name", + index="century", + aggregate_function="count", + values="last_name" + ).to_native() + ) \ No newline at end of file From 6f79ab4336f366d90c2e652ee7e0b711c99c4b6f Mon Sep 17 00:00:00 2001 From: eyrei123 Date: Thu, 6 Nov 2025 20:11:13 +0000 Subject: [PATCH 2/8] Line length issues --- narwhals-python/exercise_solution.py | 7 +++++- narwhals-python/universal_processing.py | 30 ++++++++++++------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/narwhals-python/exercise_solution.py b/narwhals-python/exercise_solution.py index d07955980b..052fcd8126 100644 --- a/narwhals-python/exercise_solution.py +++ b/narwhals-python/exercise_solution.py @@ -5,7 +5,12 @@ def rowling_books(df: IntoFrameT, lf: IntoFrameT) -> IntoFrameT: return ( nw.from_native(df) - .join(nw.from_native(lf).filter(nw.col("last_name").str.contains("Rowling")).collect(), on="author_id") + .join( + nw.from_native(lf) + .filter(nw.col("last_name").str.contains("Rowling")) + .collect(), + on="author_id", + ) .select(["book_title", "year_published", "first_name", "last_name"]) .sort("year_published") .to_pandas() diff --git a/narwhals-python/universal_processing.py b/narwhals-python/universal_processing.py index 208fe63034..60883734b9 100644 --- a/narwhals-python/universal_processing.py +++ b/narwhals-python/universal_processing.py @@ -11,14 +11,10 @@ def universal_groupby_v1(df: IntoFrameT) -> IntoFrameT: .to_native() ) + @nw.narwhalify def universal_groupby_v2(df: FrameT) -> FrameT: - return ( - df - .group_by("party_name") - .agg(nw.col("last_name").count()) - .sort("party_name") - ) + return df.group_by("party_name").agg(nw.col("last_name").count()).sort("party_name") def universal_groupby_v3(df: IntoFrameT) -> IntoFrameT: @@ -33,13 +29,14 @@ def universal_groupby_v3(df: IntoFrameT) -> IntoFrameT: def universal_pivot_v1(df: IntoFrameT) -> IntoFrameT: return ( - nw.from_native(df) - .pivot( - on="party_name", - index="century", - aggregate_function="count", - values="last_name" - ).to_native() + nw.from_native(df) + .pivot( + on="party_name", + index="century", + aggregate_function="count", + values="last_name", + ) + .to_native() ) @@ -52,6 +49,7 @@ def universal_pivot_v2(df: IntoFrameT) -> IntoFrameT: on="party_name", index="century", aggregate_function="count", - values="last_name" - ).to_native() - ) \ No newline at end of file + values="last_name", + ) + .to_native() + ) From 8cb4d2802d410847c05283ee82fd7451ba149485 Mon Sep 17 00:00:00 2001 From: eyrei123 Date: Thu, 6 Nov 2025 20:18:30 +0000 Subject: [PATCH 3/8] line length --- narwhals-python/universal_processing.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/narwhals-python/universal_processing.py b/narwhals-python/universal_processing.py index 60883734b9..973aa2b235 100644 --- a/narwhals-python/universal_processing.py +++ b/narwhals-python/universal_processing.py @@ -14,7 +14,11 @@ def universal_groupby_v1(df: IntoFrameT) -> IntoFrameT: @nw.narwhalify def universal_groupby_v2(df: FrameT) -> FrameT: - return df.group_by("party_name").agg(nw.col("last_name").count()).sort("party_name") + return ( + df.group_by("party_name") + .agg(nw.col("last_name").count()) + .sort("party_name") + ) def universal_groupby_v3(df: IntoFrameT) -> IntoFrameT: From b2132c6818575797b36c34f4de6d7edac64176e2 Mon Sep 17 00:00:00 2001 From: eyrei123 <88923476+eyrei123@users.noreply.github.com> Date: Thu, 13 Nov 2025 10:28:46 +0000 Subject: [PATCH 4/8] Fix aggregate_function in pivot calls Reversal of `values and `aggregate_function` parameters --- narwhals-python/universal_processing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/narwhals-python/universal_processing.py b/narwhals-python/universal_processing.py index 973aa2b235..937bc3946d 100644 --- a/narwhals-python/universal_processing.py +++ b/narwhals-python/universal_processing.py @@ -37,8 +37,8 @@ def universal_pivot_v1(df: IntoFrameT) -> IntoFrameT: .pivot( on="party_name", index="century", - aggregate_function="count", values="last_name", + aggregate_function="count" ) .to_native() ) @@ -52,8 +52,8 @@ def universal_pivot_v2(df: IntoFrameT) -> IntoFrameT: .pivot( on="party_name", index="century", - aggregate_function="count", values="last_name", + aggregate_function="count" ) .to_native() ) From 2ac201d1073e23c89210bb0c2c891d8569827fb6 Mon Sep 17 00:00:00 2001 From: eyrei123 <88923476+eyrei123@users.noreply.github.com> Date: Thu, 13 Nov 2025 11:14:18 +0000 Subject: [PATCH 5/8] Update universal_processing.py Missing comma --- narwhals-python/universal_processing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/narwhals-python/universal_processing.py b/narwhals-python/universal_processing.py index 937bc3946d..9610e565a2 100644 --- a/narwhals-python/universal_processing.py +++ b/narwhals-python/universal_processing.py @@ -38,7 +38,7 @@ def universal_pivot_v1(df: IntoFrameT) -> IntoFrameT: on="party_name", index="century", values="last_name", - aggregate_function="count" + aggregate_function="count", ) .to_native() ) @@ -53,7 +53,7 @@ def universal_pivot_v2(df: IntoFrameT) -> IntoFrameT: on="party_name", index="century", values="last_name", - aggregate_function="count" + aggregate_function="count", ) .to_native() ) From 79a11be645e66eb9e8500a6045bc3d1f3111fdad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Zaczy=C5=84ski?= Date: Sun, 16 Nov 2025 14:50:18 +0100 Subject: [PATCH 6/8] Update the README file --- narwhals-python/README.md | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/narwhals-python/README.md b/narwhals-python/README.md index ceb2a03db9..cfcee9f1ae 100644 --- a/narwhals-python/README.md +++ b/narwhals-python/README.md @@ -1,18 +1,14 @@ -This file contains the downloadable code from the RealPython tutorial: \[Writing DataFrame Agnostic Python Code With Narwhals](https://realpython.com/dataframe-agnostic-code-with-narwhals-python/) +# Writing DataFrame-Agnostic Python Code With Narwhals +This folder contains the downloadable code from the Real Python tutorial: [Writing DataFrame-Agnostic Python Code With Narwhals](https://realpython.com/python-narwhals/). - -authors.parquet - File of data for main sections of the tutorial. - -books.parquet - File of data for the self study section of the tutorial. - -presidents.parquet - File of data for the self study section of the tutorial. - - - -exercise\_solution.py - File containing a possible solution to the self study exercise. - -universal\_processing.py - File containing functions used in the main sections of the tutorial. +| File | Description | +|--------------------------- |----------------------------------------------------- | +| `authors.parquet` | Data for main sections of the tutorial | +| `books.parquet` | Data for the self study section of the tutorial | +| `presidents.parquet` | Data for the self study section of the tutorial | +| `exercise_solution.py` | A possible solution to the self study exercise | +| `universal_processing.py` | Functions used in the main sections of the tutorial | From 179eaf71d39efad4023adb2c3bcf9fe4f774801f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Zaczy=C5=84ski?= Date: Sun, 16 Nov 2025 15:57:52 +0100 Subject: [PATCH 7/8] Update code --- narwhals-python/universal_processing.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/narwhals-python/universal_processing.py b/narwhals-python/universal_processing.py index 9610e565a2..a35a76cf5d 100644 --- a/narwhals-python/universal_processing.py +++ b/narwhals-python/universal_processing.py @@ -45,15 +45,12 @@ def universal_pivot_v1(df: IntoFrameT) -> IntoFrameT: def universal_pivot_v2(df: IntoFrameT) -> IntoFrameT: - if isinstance(nw.from_native(df), nw.LazyFrame): - df = nw.from_native(df).collect() - return ( - nw.from_native(df) - .pivot( - on="party_name", - index="century", - values="last_name", - aggregate_function="count", - ) - .to_native() - ) + df = nw.from_native(df) + if isinstance(df, nw.LazyFrame): + df = df.collect() + return df.pivot( + on="party_name", + index="century", + values="last_name", + aggregate_function="count", + ).to_native() From c71476cba087c07f2926ee207558e0fbfef0883f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Zaczy=C5=84ski?= Date: Thu, 27 Nov 2025 20:18:08 +0100 Subject: [PATCH 8/8] Update README --- narwhals-python/README.md | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/narwhals-python/README.md b/narwhals-python/README.md index cfcee9f1ae..8e4db715ac 100644 --- a/narwhals-python/README.md +++ b/narwhals-python/README.md @@ -1,16 +1,11 @@ # Writing DataFrame-Agnostic Python Code With Narwhals -This folder contains the downloadable code from the Real Python tutorial: [Writing DataFrame-Agnostic Python Code With Narwhals](https://realpython.com/python-narwhals/). - -| File | Description | -|--------------------------- |----------------------------------------------------- | -| `authors.parquet` | Data for main sections of the tutorial | -| `books.parquet` | Data for the self study section of the tutorial | -| `presidents.parquet` | Data for the self study section of the tutorial | -| `exercise_solution.py` | A possible solution to the self study exercise | -| `universal_processing.py` | Functions used in the main sections of the tutorial | - - - - - +This folder contains the downloadable code from the Real Python tutorial: [Writing DataFrame-Agnostic Python Code With Narwhals](https://realpython.com/narwhals-python/). + +| File | Description | +|---------------------------|-----------------------------------------------------| +| `presidents.parquet` | Data for main sections of the tutorial | +| `universal_processing.py` | Functions used in the main sections of the tutorial | +| `authors.parquet` | Data for the self study section of the tutorial | +| `books.parquet` | Data for the self study section of the tutorial | +| `exercise_solution.py` | A possible solution to the self study exercise |