narwhals-map 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- narwhals_map-0.1.0/PKG-INFO +45 -0
- narwhals_map-0.1.0/README.md +29 -0
- narwhals_map-0.1.0/pyproject.toml +40 -0
- narwhals_map-0.1.0/src/narwhals_map/__init__.py +5 -0
- narwhals_map-0.1.0/src/narwhals_map/_arrow/__init__.py +0 -0
- narwhals_map-0.1.0/src/narwhals_map/_arrow/expr_map.py +18 -0
- narwhals_map-0.1.0/src/narwhals_map/_arrow/series_map.py +14 -0
- narwhals_map-0.1.0/src/narwhals_map/_compliant/__init__.py +0 -0
- narwhals_map-0.1.0/src/narwhals_map/_compliant/namespace.py +14 -0
- narwhals_map-0.1.0/src/narwhals_map/_dtype.py +71 -0
- narwhals_map-0.1.0/src/narwhals_map/_ibis/__init__.py +0 -0
- narwhals_map-0.1.0/src/narwhals_map/_ibis/expr_map.py +15 -0
- narwhals_map-0.1.0/src/narwhals_map/_narwhals_patch.py +105 -0
- narwhals_map-0.1.0/src/narwhals_map/_polars/__init__.py +0 -0
- narwhals_map-0.1.0/src/narwhals_map/_polars/expr_map.py +14 -0
- narwhals_map-0.1.0/src/narwhals_map/_polars/series_map.py +14 -0
- narwhals_map-0.1.0/src/narwhals_map/_version.py +1 -0
- narwhals_map-0.1.0/src/narwhals_map/expr_map.py +18 -0
- narwhals_map-0.1.0/src/narwhals_map/py.typed +0 -0
- narwhals_map-0.1.0/src/narwhals_map/series_map.py +14 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: narwhals-map
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author: danielgafni
|
|
6
|
+
Author-email: danielgafni <danielgafni16@gmail.com>
|
|
7
|
+
Requires-Dist: ibis-framework>=12.0.0 ; extra == 'ibis'
|
|
8
|
+
Requires-Dist: polars>=1.39.3 ; extra == 'polars'
|
|
9
|
+
Requires-Dist: polars-map>=0.2.0 ; extra == 'polars'
|
|
10
|
+
Requires-Dist: pyarrow>=23.0.1 ; extra == 'pyarrow'
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Provides-Extra: ibis
|
|
13
|
+
Provides-Extra: polars
|
|
14
|
+
Provides-Extra: pyarrow
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# narwhals-map
|
|
18
|
+
|
|
19
|
+
An experimental Narwhals plugin adding `Map` datatype.
|
|
20
|
+
|
|
21
|
+
> [!TIP]
|
|
22
|
+
> See [`narwhals-dev/narwhals#3525`](https://github.com/narwhals-dev/narwhals/issues/3525) issue for more info.
|
|
23
|
+
|
|
24
|
+
`Map` is natively supported across all backends except for Polars.
|
|
25
|
+
|
|
26
|
+
Supported Narwhals backends:
|
|
27
|
+
- Arrow
|
|
28
|
+
- Ibis
|
|
29
|
+
- Polars (via [`polars-map`](https://github.com/hafaio/polars-map))
|
|
30
|
+
|
|
31
|
+
Currently monkey-patches Narwhals to expose a new `nw.col.map` namespace.
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
import narwhals as nw
|
|
37
|
+
import narwhals_map # registers the Map dtype and .map namespace
|
|
38
|
+
|
|
39
|
+
df = nw.from_native(native_df) # use polars_map.Map for Polars-backed frames
|
|
40
|
+
result = df.select(nw.col("map_col").map.get("key1"))
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Known Limitations
|
|
44
|
+
|
|
45
|
+
- **`.to_arrow()` on Polars-backed frames**: Polars (via `polars-map`) stores maps as `List(Struct({key, value}))` internally. Calling `.to_arrow()` on a Polars-backed Narwhals frame produces `list<struct<key, value>>` columns instead of Arrow `map` types. PyArrow and Ibis backends are unaffected.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# narwhals-map
|
|
2
|
+
|
|
3
|
+
An experimental Narwhals plugin adding `Map` datatype.
|
|
4
|
+
|
|
5
|
+
> [!TIP]
|
|
6
|
+
> See [`narwhals-dev/narwhals#3525`](https://github.com/narwhals-dev/narwhals/issues/3525) issue for more info.
|
|
7
|
+
|
|
8
|
+
`Map` is natively supported across all backends except for Polars.
|
|
9
|
+
|
|
10
|
+
Supported Narwhals backends:
|
|
11
|
+
- Arrow
|
|
12
|
+
- Ibis
|
|
13
|
+
- Polars (via [`polars-map`](https://github.com/hafaio/polars-map))
|
|
14
|
+
|
|
15
|
+
Currently monkey-patches Narwhals to expose a new `nw.col.map` namespace.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
import narwhals as nw
|
|
21
|
+
import narwhals_map # registers the Map dtype and .map namespace
|
|
22
|
+
|
|
23
|
+
df = nw.from_native(native_df) # use polars_map.Map for Polars-backed frames
|
|
24
|
+
result = df.select(nw.col("map_col").map.get("key1"))
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Known Limitations
|
|
28
|
+
|
|
29
|
+
- **`.to_arrow()` on Polars-backed frames**: Polars (via `polars-map`) stores maps as `List(Struct({key, value}))` internally. Calling `.to_arrow()` on a Polars-backed Narwhals frame produces `list<struct<key, value>>` columns instead of Arrow `map` types. PyArrow and Ibis backends are unaffected.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "narwhals-map"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Add your description here"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "danielgafni", email = "danielgafni16@gmail.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = [
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[project.optional-dependencies]
|
|
14
|
+
pyarrow = [
|
|
15
|
+
"pyarrow>=23.0.1",
|
|
16
|
+
]
|
|
17
|
+
polars = [
|
|
18
|
+
"polars>=1.39.3",
|
|
19
|
+
"polars-map>=0.2.0",
|
|
20
|
+
]
|
|
21
|
+
ibis = [
|
|
22
|
+
"ibis-framework>=12.0.0",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[build-system]
|
|
26
|
+
requires = ["uv_build>=0.10.4,<0.11.0"]
|
|
27
|
+
build-backend = "uv_build"
|
|
28
|
+
|
|
29
|
+
[dependency-groups]
|
|
30
|
+
dev = [
|
|
31
|
+
# narwhals has to depend on us I guess?
|
|
32
|
+
# so we can't depend on it
|
|
33
|
+
"narwhals>=2.18.1",
|
|
34
|
+
"prek>=0.3.8",
|
|
35
|
+
"pyrefly>=0.59.1",
|
|
36
|
+
"pytest>=9.0.2",
|
|
37
|
+
"pytest-cases>=3.10.1",
|
|
38
|
+
"ruff>=0.15.9",
|
|
39
|
+
"ibis-framework[duckdb]>=12.0.0",
|
|
40
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from narwhals._compliant.expr import EagerExprNamespace
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ArrowExprMapNamespace(EagerExprNamespace): # type: ignore[type-arg]
|
|
7
|
+
def get(self, key: Any) -> Any:
|
|
8
|
+
compliant = self._compliant_expr
|
|
9
|
+
|
|
10
|
+
def inner(df): # type: ignore[no-untyped-def]
|
|
11
|
+
return [series.map.get(key=key) for series in compliant(df)] # type: ignore[attr-defined]
|
|
12
|
+
|
|
13
|
+
return compliant._from_callable(
|
|
14
|
+
inner,
|
|
15
|
+
evaluate_output_names=compliant._evaluate_output_names,
|
|
16
|
+
alias_output_names=compliant._alias_output_names,
|
|
17
|
+
context=compliant,
|
|
18
|
+
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any
|
|
2
|
+
|
|
3
|
+
import pyarrow.compute as pc
|
|
4
|
+
from narwhals._arrow.utils import ArrowSeriesNamespace
|
|
5
|
+
|
|
6
|
+
from narwhals_map._compliant.namespace import MapNamespace
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from narwhals._arrow.series import ArrowSeries
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ArrowSeriesMapNamespace(ArrowSeriesNamespace, MapNamespace["ArrowSeries"]):
|
|
13
|
+
def get(self, key: Any) -> "ArrowSeries":
|
|
14
|
+
return self.with_native(pc.map_lookup(self.native, key, "first")).alias(str(key)) # pyrefly: ignore [missing-attribute]
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Protocol, TypeVar
|
|
2
|
+
|
|
3
|
+
from narwhals._utils import CompliantT_co, _StoresCompliant
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from narwhals._compliant.typing import Accessor
|
|
7
|
+
|
|
8
|
+
T = TypeVar("T")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class MapNamespace(_StoresCompliant[CompliantT_co], Protocol[CompliantT_co]):
|
|
12
|
+
_accessor: ClassVar["Accessor"] = "map" # type: ignore[assignment]
|
|
13
|
+
|
|
14
|
+
def get(self, key: Any) -> CompliantT_co: ...
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections import OrderedDict
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from narwhals.dtypes import DType, DTypeClass, NestedType
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from narwhals.typing import IntoDType
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Map(NestedType):
|
|
13
|
+
"""Map composite type.
|
|
14
|
+
|
|
15
|
+
Arguments:
|
|
16
|
+
key: The key data type of the map. Must be hashable.
|
|
17
|
+
value: The value data type of the map.
|
|
18
|
+
|
|
19
|
+
Examples:
|
|
20
|
+
>>> import pyarrow as pa
|
|
21
|
+
>>> import narwhals as nw
|
|
22
|
+
>>> s_native = pa.map_(pa.string(), pa.int64())
|
|
23
|
+
... [[("key1", 1), ("key2", 2)]]
|
|
24
|
+
... )
|
|
25
|
+
>>> nw.from_native(s_native, series_only=True).dtype
|
|
26
|
+
Map(String, Int64)
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
__slots__ = (
|
|
30
|
+
"key",
|
|
31
|
+
"value",
|
|
32
|
+
)
|
|
33
|
+
key: IntoDType
|
|
34
|
+
value: IntoDType
|
|
35
|
+
"""The key and value data types of the map."""
|
|
36
|
+
|
|
37
|
+
def __init__(self, key: IntoDType, value: IntoDType) -> None:
|
|
38
|
+
self.key = key
|
|
39
|
+
self.value = value
|
|
40
|
+
|
|
41
|
+
def __eq__(self, other: DType | type[DType]) -> bool: # type: ignore[override]
|
|
42
|
+
"""Check if this Map is equivalent to another DType.
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
>>> import narwhals as nw
|
|
46
|
+
>>> nw.Map(nw.Int64, nw.Int64) == nw.Map(nw.Int64, nw.Int64)
|
|
47
|
+
True
|
|
48
|
+
>>> nw.Map(nw.Int64, nw.Int64) == nw.Map(nw.Int64, nw.Boolean)
|
|
49
|
+
False
|
|
50
|
+
|
|
51
|
+
If a parent type is not specific about its inner type, we infer it as equal
|
|
52
|
+
|
|
53
|
+
>>> nw.Map(nw.Int64, nw.Int64) == nw.Map
|
|
54
|
+
True
|
|
55
|
+
"""
|
|
56
|
+
if type(other) is DTypeClass and issubclass(other, self.__class__):
|
|
57
|
+
return True
|
|
58
|
+
if isinstance(other, self.__class__):
|
|
59
|
+
return (self.key, self.value) == (other.key, other.value)
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
def __hash__(self) -> int:
|
|
63
|
+
return hash((self.__class__, (self.key, self.value)))
|
|
64
|
+
|
|
65
|
+
def __repr__(self) -> str:
|
|
66
|
+
class_name = self.__class__.__name__
|
|
67
|
+
return f"{class_name}({self.key}, {self.value})"
|
|
68
|
+
|
|
69
|
+
def to_schema(self) -> OrderedDict[str, IntoDType]:
|
|
70
|
+
"""Return Map dtype as a schema dict."""
|
|
71
|
+
return OrderedDict({"key": self.key, "value": self.value})
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from narwhals._compliant import LazyExprNamespace
|
|
6
|
+
|
|
7
|
+
from narwhals_map._compliant.namespace import MapNamespace
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from narwhals._ibis.expr import IbisExpr
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class IbisExprMapNamespace(LazyExprNamespace["IbisExpr"], MapNamespace["IbisExpr"]):
|
|
14
|
+
def get(self, key: Any) -> IbisExpr:
|
|
15
|
+
return self.compliant._with_callable(lambda expr: expr.get(key).name(str(key)))
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Monkey-patch narwhals internals to add Map dtype and .map namespace support."""
|
|
2
|
+
|
|
3
|
+
from narwhals.expr import Expr
|
|
4
|
+
from narwhals.series import Series
|
|
5
|
+
|
|
6
|
+
from narwhals_map._dtype import Map
|
|
7
|
+
from narwhals_map.expr_map import ExprMapNamespace
|
|
8
|
+
from narwhals_map.series_map import SeriesMapNamespace
|
|
9
|
+
|
|
10
|
+
# --- Public API namespace patches (always available) ---
|
|
11
|
+
|
|
12
|
+
Expr.map = property(lambda self: ExprMapNamespace(self)) # type: ignore[attr-defined]
|
|
13
|
+
Series.map = property(lambda self: SeriesMapNamespace(self)) # type: ignore[attr-defined]
|
|
14
|
+
|
|
15
|
+
# --- PyArrow backend (optional) ---
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
import pyarrow as pa
|
|
19
|
+
from narwhals._arrow import utils as _arrow_utils
|
|
20
|
+
from narwhals._arrow.series import ArrowSeries
|
|
21
|
+
from narwhals._compliant.expr import EagerExpr
|
|
22
|
+
|
|
23
|
+
from narwhals_map._arrow.expr_map import ArrowExprMapNamespace
|
|
24
|
+
from narwhals_map._arrow.series_map import ArrowSeriesMapNamespace
|
|
25
|
+
|
|
26
|
+
ArrowSeries.map = property(lambda self: ArrowSeriesMapNamespace(self)) # type: ignore[attr-defined]
|
|
27
|
+
EagerExpr.map = property(lambda self: ArrowExprMapNamespace(self)) # type: ignore[attr-defined]
|
|
28
|
+
|
|
29
|
+
_orig_arrow_native_to_narwhals_dtype = _arrow_utils.native_to_narwhals_dtype
|
|
30
|
+
|
|
31
|
+
def _patched_arrow_native_to_narwhals_dtype(dtype, version): # type: ignore[no-untyped-def]
|
|
32
|
+
if isinstance(dtype, pa.MapType):
|
|
33
|
+
return Map(
|
|
34
|
+
_patched_arrow_native_to_narwhals_dtype(dtype.key_type, version),
|
|
35
|
+
_patched_arrow_native_to_narwhals_dtype(dtype.item_type, version),
|
|
36
|
+
)
|
|
37
|
+
return _orig_arrow_native_to_narwhals_dtype(dtype, version)
|
|
38
|
+
|
|
39
|
+
_arrow_utils.native_to_narwhals_dtype = _patched_arrow_native_to_narwhals_dtype # type: ignore[assignment]
|
|
40
|
+
|
|
41
|
+
_orig_arrow_narwhals_to_native_dtype = _arrow_utils.narwhals_to_native_dtype
|
|
42
|
+
|
|
43
|
+
def _patched_arrow_narwhals_to_native_dtype(dtype, version): # type: ignore[no-untyped-def]
|
|
44
|
+
if isinstance(dtype, Map):
|
|
45
|
+
return pa.map_(
|
|
46
|
+
_orig_arrow_narwhals_to_native_dtype(dtype.key, version),
|
|
47
|
+
_orig_arrow_narwhals_to_native_dtype(dtype.value, version),
|
|
48
|
+
)
|
|
49
|
+
return _orig_arrow_narwhals_to_native_dtype(dtype, version)
|
|
50
|
+
|
|
51
|
+
_arrow_utils.narwhals_to_native_dtype = _patched_arrow_narwhals_to_native_dtype # type: ignore[assignment]
|
|
52
|
+
except ImportError:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
# --- Polars backend (optional) ---
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
import polars_map as _polars_map
|
|
59
|
+
from narwhals._polars import utils as _polars_utils
|
|
60
|
+
from narwhals._polars.expr import PolarsExpr
|
|
61
|
+
from narwhals._polars.series import PolarsSeries
|
|
62
|
+
|
|
63
|
+
from narwhals_map._polars.expr_map import PolarsExprMapNamespace
|
|
64
|
+
from narwhals_map._polars.series_map import PolarsSeriesMapNamespace
|
|
65
|
+
|
|
66
|
+
PolarsExpr.map = property(lambda self: PolarsExprMapNamespace(self)) # type: ignore[attr-defined]
|
|
67
|
+
PolarsSeries.map = property(lambda self: PolarsSeriesMapNamespace(self)) # type: ignore[attr-defined]
|
|
68
|
+
|
|
69
|
+
_orig_polars_native_to_narwhals_dtype = _polars_utils.native_to_narwhals_dtype
|
|
70
|
+
|
|
71
|
+
def _patched_polars_native_to_narwhals_dtype(dtype, version): # type: ignore[no-untyped-def]
|
|
72
|
+
if isinstance(dtype, _polars_map.Map):
|
|
73
|
+
return Map(
|
|
74
|
+
_patched_polars_native_to_narwhals_dtype(dtype.key, version),
|
|
75
|
+
_patched_polars_native_to_narwhals_dtype(dtype.value, version),
|
|
76
|
+
)
|
|
77
|
+
return _orig_polars_native_to_narwhals_dtype(dtype, version)
|
|
78
|
+
|
|
79
|
+
_polars_utils.native_to_narwhals_dtype = _patched_polars_native_to_narwhals_dtype # type: ignore[assignment]
|
|
80
|
+
except ImportError:
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
# --- Ibis backend (optional) ---
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
from narwhals._ibis import utils as _ibis_utils
|
|
87
|
+
from narwhals._ibis.expr import IbisExpr
|
|
88
|
+
|
|
89
|
+
from narwhals_map._ibis.expr_map import IbisExprMapNamespace
|
|
90
|
+
|
|
91
|
+
IbisExpr.map = property(lambda self: IbisExprMapNamespace(self)) # type: ignore[attr-defined]
|
|
92
|
+
|
|
93
|
+
_orig_ibis_native_to_narwhals_dtype = _ibis_utils.native_to_narwhals_dtype
|
|
94
|
+
|
|
95
|
+
def _patched_ibis_native_to_narwhals_dtype(ibis_dtype, version): # type: ignore[no-untyped-def]
|
|
96
|
+
if ibis_dtype.is_map():
|
|
97
|
+
return Map(
|
|
98
|
+
_patched_ibis_native_to_narwhals_dtype(ibis_dtype.key_type, version),
|
|
99
|
+
_patched_ibis_native_to_narwhals_dtype(ibis_dtype.value_type, version),
|
|
100
|
+
)
|
|
101
|
+
return _orig_ibis_native_to_narwhals_dtype(ibis_dtype, version)
|
|
102
|
+
|
|
103
|
+
_ibis_utils.native_to_narwhals_dtype = _patched_ibis_native_to_narwhals_dtype # type: ignore[assignment]
|
|
104
|
+
except ImportError:
|
|
105
|
+
pass
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any
|
|
2
|
+
|
|
3
|
+
import polars_map # noqa: F401 - registers .map on pl.Expr
|
|
4
|
+
from narwhals._polars.expr import PolarsExprNamespace
|
|
5
|
+
|
|
6
|
+
from narwhals_map._compliant.namespace import MapNamespace
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from narwhals._polars.expr import PolarsExpr
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PolarsExprMapNamespace(PolarsExprNamespace, MapNamespace["PolarsExpr"]):
|
|
13
|
+
def get(self, key: Any) -> "PolarsExpr":
|
|
14
|
+
return self.compliant._with_native(self.native.map.get(key)) # pyrefly: ignore [missing-attribute]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any
|
|
2
|
+
|
|
3
|
+
from narwhals._polars.series import PolarsSeriesNamespace
|
|
4
|
+
|
|
5
|
+
from narwhals_map._compliant.namespace import MapNamespace
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from narwhals._polars.series import PolarsSeries
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PolarsSeriesMapNamespace(PolarsSeriesNamespace, MapNamespace["PolarsSeries"]):
|
|
12
|
+
def get(self, key: Any) -> "PolarsSeries":
|
|
13
|
+
ns = self.__narwhals_namespace__()
|
|
14
|
+
return self.to_frame().select(ns.col(self.name).map.get(key)).get_column(str(key))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar
|
|
2
|
+
|
|
3
|
+
from narwhals._expression_parsing import ExprKind, ExprNode
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from narwhals.expr import Expr
|
|
7
|
+
|
|
8
|
+
ExprT = TypeVar("ExprT", bound="Expr")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ExprMapNamespace(Generic[ExprT]):
|
|
12
|
+
def __init__(self, expr: ExprT) -> None:
|
|
13
|
+
self._expr = expr
|
|
14
|
+
|
|
15
|
+
def get(self, key: Any) -> ExprT:
|
|
16
|
+
return self._expr._append_node(ExprNode(ExprKind.ELEMENTWISE, "map.get", key=key))._append_node(
|
|
17
|
+
ExprNode(ExprKind.ELEMENTWISE, "alias", name=str(key))
|
|
18
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from narwhals.series import Series
|
|
5
|
+
|
|
6
|
+
SeriesT = TypeVar("SeriesT", bound="Series")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SeriesMapNamespace(Generic[SeriesT]):
|
|
10
|
+
def __init__(self, series: SeriesT) -> None:
|
|
11
|
+
self._narwhals_series = series
|
|
12
|
+
|
|
13
|
+
def get(self, key: Any) -> SeriesT:
|
|
14
|
+
return self._narwhals_series._with_compliant(self._narwhals_series._compliant_series.map.get(key)) # pyrefly: ignore [missing-attribute]
|