diff --git a/narwhals/pandas_like/utils.py b/narwhals/pandas_like/utils.py index 17f59971c..8143b8553 100644 --- a/narwhals/pandas_like/utils.py +++ b/narwhals/pandas_like/utils.py @@ -99,6 +99,7 @@ def parse_into_expr(implementation: str, into_expr: IntoPandasExpr) -> PandasExp from narwhals.expression import Expr from narwhals.pandas_like.expr import PandasExpr from narwhals.pandas_like.namespace import PandasNamespace + from narwhals.pandas_like.series import PandasSeries plx = PandasNamespace(implementation=implementation) @@ -106,6 +107,8 @@ def parse_into_expr(implementation: str, into_expr: IntoPandasExpr) -> PandasExp return into_expr if isinstance(into_expr, Expr): return into_expr._call(plx) + if isinstance(into_expr, PandasSeries): + return plx._create_expr_from_series(into_expr) if isinstance(into_expr, str): return plx.col(into_expr) msg = f"Expected IntoExpr, got {type(into_expr)}" diff --git a/narwhals/series.py b/narwhals/series.py index 951f3366d..a99cba85e 100644 --- a/narwhals/series.py +++ b/narwhals/series.py @@ -134,3 +134,9 @@ def mean(self) -> Any: def std(self) -> Any: return self._series.std() + + def __gt__(self, other: Any) -> Series: + return self._series.__gt__(self._extract_native(other)) # type: ignore[no-any-return] + + def __lt__(self, other: Any) -> Series: + return self._series.__lt__(self._extract_native(other)) # type: ignore[no-any-return] diff --git a/requirements-dev.txt b/requirements-dev.txt index dcc57d5f6..452f9c615 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,5 @@ covdefaults +modin[dask] pandas polars pre-commit diff --git a/tests/test_common.py b/tests/test_common.py index e43a45dbf..bef5fdb24 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -1,7 +1,9 @@ from __future__ import annotations +import warnings from typing import Any +import modin.pandas as mpd import numpy as np import pandas as pd import polars as pl @@ -13,6 +15,11 @@ df_pandas = pd.DataFrame({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}) df_polars = pl.DataFrame({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}) df_lazy = pl.LazyFrame({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}) +with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=UserWarning) + df_mpd = mpd.DataFrame( + pd.DataFrame({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}) + ) @pytest.mark.parametrize( @@ -33,7 +40,7 @@ def test_sort(df_raw: Any) -> None: @pytest.mark.parametrize( "df_raw", - [df_pandas, df_polars, df_lazy], + [df_pandas, df_lazy], ) def test_filter(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) @@ -45,7 +52,19 @@ def test_filter(df_raw: Any) -> None: @pytest.mark.parametrize( "df_raw", - [df_pandas, df_polars, df_lazy], + [df_pandas], +) +def test_filter_series(df_raw: Any) -> None: + df = nw.DataFrame(df_raw) + result = df.filter(df["a"] > 1) + result_native = nw.to_native(result) + expected = {"a": [3, 2], "b": [4, 6], "z": [8.0, 9.0]} + compare_dicts(result_native, expected) + + +@pytest.mark.parametrize( + "df_raw", + [df_pandas, df_lazy], ) def test_add(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) @@ -66,7 +85,7 @@ def test_add(df_raw: Any) -> None: @pytest.mark.parametrize( "df_raw", - [df_pandas, df_polars, df_lazy], + [df_pandas, df_lazy], ) def test_double(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) @@ -76,7 +95,7 @@ def test_double(df_raw: Any) -> None: compare_dicts(result_native, expected) -@pytest.mark.parametrize("df_raw", [df_pandas, df_polars, df_lazy]) +@pytest.mark.parametrize("df_raw", [df_pandas, df_lazy]) def test_sumh(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) result = df.with_columns(horizonal_sum=nw.sum_horizontal(nw.col("a"), nw.col("b"))) @@ -90,7 +109,7 @@ def test_sumh(df_raw: Any) -> None: compare_dicts(result_native, expected) -@pytest.mark.parametrize("df_raw", [df_pandas, df_polars, df_lazy]) +@pytest.mark.parametrize("df_raw", [df_pandas, df_lazy]) def test_sumh_literal(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) result = df.with_columns(horizonal_sum=nw.sum_horizontal("a", nw.col("b"))) @@ -104,7 +123,7 @@ def test_sumh_literal(df_raw: Any) -> None: compare_dicts(result_native, expected) -@pytest.mark.parametrize("df_raw", [df_pandas, df_polars, df_lazy]) +@pytest.mark.parametrize("df_raw", [df_pandas, df_lazy]) def test_sum_all(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) result = df.select(nw.all().sum()) @@ -113,7 +132,7 @@ def test_sum_all(df_raw: Any) -> None: compare_dicts(result_native, expected) -@pytest.mark.parametrize("df_raw", [df_pandas, df_polars, df_lazy]) +@pytest.mark.parametrize("df_raw", [df_pandas, df_lazy]) def test_double_selected(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) result = df.select(nw.col("a", "b") * 2) @@ -122,7 +141,7 @@ def test_double_selected(df_raw: Any) -> None: compare_dicts(result_native, expected) -@pytest.mark.parametrize("df_raw", [df_pandas, df_polars, df_lazy]) +@pytest.mark.parametrize("df_raw", [df_pandas, df_lazy]) def test_rename(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) result = df.rename({"a": "x", "b": "y"}) @@ -131,7 +150,7 @@ def test_rename(df_raw: Any) -> None: compare_dicts(result_native, expected) -@pytest.mark.parametrize("df_raw", [df_pandas, df_polars, df_lazy]) +@pytest.mark.parametrize("df_raw", [df_pandas, df_lazy]) def test_join(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) df_right = df.rename({"z": "z_right"}) @@ -141,7 +160,7 @@ def test_join(df_raw: Any) -> None: compare_dicts(result_native, expected) -@pytest.mark.parametrize("df_raw", [df_pandas, df_polars, df_lazy]) +@pytest.mark.parametrize("df_raw", [df_pandas, df_lazy]) def test_schema(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) result = df.schema @@ -149,7 +168,7 @@ def test_schema(df_raw: Any) -> None: assert result == expected -@pytest.mark.parametrize("df_raw", [df_pandas, df_polars, df_lazy]) +@pytest.mark.parametrize("df_raw", [df_pandas, df_lazy]) def test_columns(df_raw: Any) -> None: df = nw.LazyFrame(df_raw) result = df.columns @@ -158,8 +177,29 @@ def test_columns(df_raw: Any) -> None: assert all(x == y for x, y in zip(result, expected)) +@pytest.mark.parametrize("df_raw", [df_lazy]) +def test_lazy_instantiation(df_raw: Any) -> None: + with pytest.raises( + TypeError, match="Can't instantiate DataFrame from Polars LazyFrame." + ): + _ = nw.DataFrame(df_raw).shape + + +@pytest.mark.parametrize("df_raw", [df_polars, df_pandas, df_mpd]) +def test_eager_instantiation(df_raw: Any) -> None: + result = nw.DataFrame(df_raw) + result_native = nw.to_native(result) + expected = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]} + compare_dicts(result_native, expected) + + def test_accepted_dataframes() -> None: array = np.array([[0, 4.0], [2, 5]]) + with pytest.raises( + TypeError, + match="Expected pandas-like dataframe, Polars dataframe, or Polars lazyframe, got: ", + ): + nw.DataFrame(array) with pytest.raises( TypeError, match="Expected pandas-like dataframe, Polars dataframe, or Polars lazyframe, got: ",