Skip to content

Commit

Permalink
fixup
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcoGorelli committed Mar 9, 2024
1 parent 8ef02fc commit 3d1fe0d
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 96 deletions.
17 changes: 15 additions & 2 deletions narwhals/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
from narwhals import containers
from narwhals.containers import get_implementation
from narwhals.containers import is_dataframe
from narwhals.containers import is_pandas
from narwhals.containers import is_polars
from narwhals.containers import is_series
from narwhals.translate import translate_any
from narwhals.translate import translate_frame
from narwhals.translate import translate_series

__version__ = "0.2.0"

__all__ = ["translate_frame", "translate_series", "translate_any", "containers"]
__all__ = [
"translate_frame",
"translate_series",
"translate_any",
"is_dataframe",
"is_series",
"is_polars",
"is_pandas",
"get_implementation",
]
76 changes: 15 additions & 61 deletions narwhals/containers.py
Original file line number Diff line number Diff line change
@@ -1,78 +1,32 @@
# todo: simplify all of this!
try:
import polars as pl
except ModuleNotFoundError:
POLARS_AVAILABLE = False
pl = object # type: ignore[assignment]
else:
POLARS_AVAILABLE = True
try:
import pandas as pd
except ModuleNotFoundError:
PANDAS_AVAILABLE = False
pd = object
else:
PANDAS_AVAILABLE = True
try:
import cudf
except ModuleNotFoundError:
CUDF_AVAILABLE = False
cudf = object
else:
CUDF_AVAILABLE = True
try:
import modin.pandas as mpd
except ModuleNotFoundError:
MODIN_AVAILABLE = False
mpd = object
else:
MODIN_AVAILABLE = True


from typing import Any


def is_dataframe(obj: Any) -> bool:
if POLARS_AVAILABLE and isinstance(
obj, (pl.DataFrame, pl.LazyFrame, pl.Expr, pl.Series)
):
return isinstance(obj, pl.DataFrame)
from narwhals.pandas_like.dataframe import DataFrame

return isinstance(obj, DataFrame)
from narwhals.translate import get_pandas
from narwhals.translate import get_polars


def is_expr(obj: Any) -> bool:
if POLARS_AVAILABLE and isinstance(
obj, (pl.DataFrame, pl.LazyFrame, pl.Expr, pl.Series)
):
return isinstance(obj, pl.Expr)
from narwhals.pandas_like.expr import Expr

return isinstance(obj, Expr)
def is_dataframe(obj: Any) -> bool:
if (pl := get_polars()) is not None and isinstance(obj, (pl.DataFrame, pl.LazyFrame)):
return True
if (pd := get_pandas()) is not None and isinstance(obj, pd.DataFrame):
return True
raise NotImplementedError


def is_series(obj: Any) -> bool:
if POLARS_AVAILABLE and isinstance(
obj, (pl.DataFrame, pl.LazyFrame, pl.Expr, pl.Series)
):
return isinstance(obj, pl.Series)
from narwhals.pandas_like.series import Series

return isinstance(obj, Series)
if (pl := get_polars()) is not None and isinstance(obj, (pl.Series)):
return True
if (pd := get_pandas()) is not None and isinstance(obj, pd.Series):
return True
raise NotImplementedError


def get_implementation(obj: Any) -> str:
if POLARS_AVAILABLE and isinstance(
if (pl := get_polars()) is not None and isinstance(
obj, (pl.DataFrame, pl.LazyFrame, pl.Expr, pl.Series)
):
return "polars"
if PANDAS_AVAILABLE and isinstance(obj, (pd.DataFrame, pd.Series)):
if (pd := get_pandas()) is not None and isinstance(obj, (pd.DataFrame, pd.Series)):
return "pandas"
if CUDF_AVAILABLE and isinstance(obj, (cudf.DataFrame, cudf.Series)):
return "cudf"
if MODIN_AVAILABLE and isinstance(obj, mpd.DataFrame):
return "modin"
msg = f"Unknown implementation: {obj}"
raise TypeError(msg)

Expand Down
14 changes: 13 additions & 1 deletion narwhals/pandas_like/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def __repr__(self) -> str: # pragma: no cover
+ "─" * length
+ "┐\n"
+ f"|{header}|\n"
+ "| Add `._dataframe` to see native output |\n"
+ "| Add `.to_native()` to see native output |\n"
+ "└"
+ "─" * length
+ "┘\n"
Expand Down Expand Up @@ -247,6 +247,18 @@ def shape(self) -> tuple[int, int]:
)
return self._dataframe.shape # type: ignore[no-any-return]

def iter_columns(self) -> Iterable[Series]:
from narwhals.pandas_like.series import Series

if not self._is_eager:
raise RuntimeError(
"DataFrame.iter_columns can only be called when it was instantiated with `is_eager=True`"
)
return (
Series(self._dataframe[col], implementation=self._implementation)
for col in self.columns
)

def to_dict(self, *, as_series: bool = False) -> dict[str, Any]:
if not self._is_eager:
raise RuntimeError(
Expand Down
18 changes: 17 additions & 1 deletion narwhals/pandas_like/dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ class NumericType(DType):
...


class TemporalType(DType):
...


class Int64(NumericType):
...

Expand Down Expand Up @@ -69,5 +73,17 @@ class String(DType):
...


class Bool(DType):
class Boolean(DType):
...


class Datetime(DType):
...


class Date(DType):
...


class Duration(DType):
...
8 changes: 4 additions & 4 deletions narwhals/pandas_like/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Namespace(NamespaceProtocol):
UInt8 = dtypes.UInt8
Float64 = dtypes.Float64
Float32 = dtypes.Float32
Bool = dtypes.Bool
Boolean = dtypes.Boolean
String = dtypes.String

# --- not in spec ---
Expand Down Expand Up @@ -151,13 +151,13 @@ def concat(
self,
items: Iterable[DataFrame], # type: ignore[override]
*,
how: str,
how: str = "vertical",
) -> DataFrame:
dfs: list[Any] = []
kind: Any = {}
kind: Any = set()
for df in items:
dfs.append(df._dataframe)
kind.append(type(df._dataframe))
kind.add(type(df._dataframe))
if len(kind) > 1:
msg = "Can only concat DataFrames or LazyFrames, not mixtures of the two"
raise TypeError(msg)
Expand Down
4 changes: 4 additions & 0 deletions narwhals/pandas_like/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ def name(self) -> str:
def shape(self) -> tuple[int]:
return self._series.shape # type: ignore[no-any-return]

def rename(self, name: str) -> Series:
ser = self.series
return self._from_series(ser.rename(name, copy=False))

@property
def series(self) -> Any:
return self._series
Expand Down
16 changes: 9 additions & 7 deletions narwhals/pandas_like/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ def series_from_iterable(
def translate_dtype(dtype: Any) -> DType:
from narwhals.pandas_like import dtypes

if dtype == "int64":
if dtype in ("int64", "Int64"):
return dtypes.Int64()
if dtype == "int32":
return dtypes.Int32()
Expand All @@ -313,14 +313,16 @@ def translate_dtype(dtype: Any) -> DType:
return dtypes.UInt16()
if dtype == "uint8":
return dtypes.UInt8()
if dtype == "float64":
if dtype in ("float64", "Float64"):
return dtypes.Float64()
if dtype == "float32":
if dtype in ("float32", "Float32"):
return dtypes.Float32()
if dtype == "object":
if dtype in ("object", "string"):
return dtypes.String()
if dtype == "bool":
return dtypes.Bool()
if dtype in ("bool", "boolean"):
return dtypes.Boolean()
if str(dtype).startswith("datetime64"):
return dtypes.Datetime()
msg = f"Unknown dtype: {dtype}"
raise TypeError(msg)

Expand Down Expand Up @@ -354,7 +356,7 @@ def reverse_translate_dtype(dtype: DType | type[DType]) -> Any:
return "uint8"
if isinstance_or_issubclass(dtype, dtypes.String):
return "object"
if isinstance_or_issubclass(dtype, dtypes.Bool):
if isinstance_or_issubclass(dtype, dtypes.Boolean):
return "bool"
msg = f"Unknown dtype: {dtype}"
raise TypeError(msg)
Expand Down
Loading

0 comments on commit 3d1fe0d

Please sign in to comment.