
    gy                      d dl mZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d d	lm
Z
 d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ er*d dlmZ d dlZd dlZd dlZd dlm Z  d dl!m"Z" d dlm#Z# d dlm$Z$  G d dee         Z% ede%e         Z& G d dee&         Z' G d dee&         Z( G d  d!ee&         Z) G d" d#ee&         Z*y)$    )annotations)TYPE_CHECKING)Any)Callable)Generic)Iterator)Literal)Mapping)Sequence)TypeVar)overload)is_numpy_scalar)_validate_dtype)IntoSeriesT)_validate_rolling_arguments)generate_repr)parse_version)
ModuleTypeN)Self	DataFrame)DType)Implementationc                     e Zd ZdZedd       Z	 	 	 	 	 	 	 	 ddZedd       ZdddZe	dd       Z
e	dd       Z
dd	Z
dd
ZdddZddZddZedd       ZddZddZddZddZddZddZedd       Zedd       Zdddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddZddZddZddZdd Zdd!Zdd"Zdd#Z dd$Z!dd%Z"dd&Z#dd'Z$dd(Z%dd)Z&dd*dd+Z'dd*dd,Z(	 d	 	 	 	 	 dd-Z)dd.Z*dd/Z+dd0Z,dd1Z-dd2dd3Z.dd4dd5Z/dd6Z0dd7Z1	 ddddd8	 	 	 	 	 	 	 	 	 	 	 dd9Z2dd:Z3dd;Z4	 ddd<	 	 	 	 	 	 	 	 	 dd=Z5ddd>dd?Z6dd@Z7ddAZ8	 	 	 d	 	 	 	 	 	 	 ddBZ9	 d	 	 	 	 	 	 	 ddCZ:ddDZ;ddEZ<ddFZ=ddGZ>ddHZ?ddIZ@ddJZAddKZBddLZCddMZDddNZEddOZFddPZGddQZHddRZIddSZJddTZKddUZLddVZMddWZNddXZOddYZPddZZQdd[ZRdd\ZSdd]ZTdd^ZUdd_ZVdd`ZWddaZXddbZYddcZZdddZ[ddeZ\ddfZ]ddgddhZ^dddddi	 	 	 	 	 	 	 	 	 	 	 ddjZ_	 	 	 	 	 	 ddkZ`ddlZadddmZbdddnZcdddoZddddpZedqddr	 	 	 	 	 	 	 ddsZfdddtZgdduZhddvZiddwZjdd2ddxZkdd2ddyZldd2ddzZmdd2dd{Znddd|	 	 	 	 	 	 	 	 	 dd}Zoddd|	 	 	 	 	 	 	 	 	 dd~Zpdddd	 	 	 	 	 	 	 	 	 	 	 ddZqdddd	 	 	 	 	 	 	 	 	 	 	 ddZrddZsddZt	 dddg	 	 	 	 	 	 	 ddZuedd       Zvedd       Zwedd       Zxedd       Zyy)Seriesai  Narwhals Series, backed by a native series.

    !!! warning
        This class is not meant to be instantiated directly - instead:

        - If the native object is a series from one of the supported backend (e.g.
            pandas.Series, polars.Series, pyarrow.ChunkedArray), you can use
            [`narwhals.from_native`][]:
            ```py
            narwhals.from_native(native_series, allow_series=True)
            narwhals.from_native(native_series, series_only=True)
            ```

        - If the object is a generic sequence (e.g. a list or a tuple of values), you can
            create a series via [`narwhals.new_series`][]:
            ```py
            narwhals.new_series(
                name=name,
                values=values,
                native_namespace=narwhals.get_native_namespace(another_object),
            )
            ```
    c                    ddl m} |S )Nr   r   )narwhals.dataframer   )selfr   s     D/var/www/openai/venv/lib/python3.12/site-packages/narwhals/series.py
_dataframezSeries._dataframe;   s    0    c                   || _         t        |d      r|j                         | _        y dt	        |       d}t        |      )N__narwhals_series__zQExpected Polars Series or an object which implements `__narwhals_series__`, got: .)_levelhasattrr#   _compliant_seriestypeAssertionError)r   serieslevelmsgs       r   __init__zSeries.__init__A   sI     601%+%?%?%AD"efjkqfresstuC %%r!   c                .    | j                   j                  S )a  Return implementation of native Series.

        This can be useful when you need to use special-casing for features outside of
        Narwhals' scope - for example, when dealing with pandas' Period Dtype.

        Returns:
            Implementation.

        Examples:
            >>> import narwhals as nw
            >>> import pandas as pd

            >>> s_native = pd.Series([1, 2, 3])
            >>> s = nw.from_native(s_native, series_only=True)

            >>> s.implementation
            <Implementation.PANDAS: 1>

            >>> s.implementation.is_pandas()
            True

            >>> s.implementation.is_pandas_like()
            True

            >>> s.implementation.is_polars()
            False
        )r'   _implementationr   s    r   implementationzSeries.implementationN   s    : %%555r!   Nc                <    | j                   j                  ||      S )N)dtypecopy)r'   	__array__)r   r3   r4   s      r   r5   zSeries.__array__m   s    %%//e$/GGr!   c                     y N r   idxs     r   __getitem__zSeries.__getitem__p   s    25r!   c                     y r7   r8   r9   s     r   r;   zSeries.__getitem__s   s    EHr!   c                    t        |t              s#t        |      r'|j                  j                  dv r| j
                  |   S | j                  | j
                  |         S )a  Retrieve elements from the object using integer indexing or slicing.

        Arguments:
            idx: The index, slice, or sequence of indices to retrieve.

                - If `idx` is an integer, a single element is returned.
                - If `idx` is a slice or a sequence of integers,
                  a subset of the Series is returned.

        Returns:
            A single element if `idx` is an integer, else a subset of the Series.

        Examples:
            >>> from typing import Any
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_get_first_item(s_native: IntoSeriesT) -> Any:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s[0]

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_get_first_item`:

            >>> agnostic_get_first_item(s_pd)
            np.int64(1)

            >>> agnostic_get_first_item(s_pl)
            1

            >>> agnostic_get_first_item(s_pa)
            1

            We can also make a function to slice the Series:

            >>> def agnostic_slice(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s[:2].to_native()

            >>> agnostic_slice(s_pd)
            0    1
            1    2
            dtype: int64

            >>> agnostic_slice(s_pl)  # doctest:+NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i64]
            [
                1
                2
            ]

            >>> agnostic_slice(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                2
              ]
            ]
        )iu)
isinstanceintr   r3   kindr'   _from_compliant_seriesr9   s     r   r;   zSeries.__getitem__v   sS    P c3C SYY^^z%A))#..**4+A+A#+FGGr!   c                6    | j                   j                         S r7   )r'   __native_namespace__r0   s    r   rE   zSeries.__native_namespace__   s    %%::<<r!   c                   | j                   j                  }t        |d      r|j                  |      S 	 ddl}t        |j                        dk  rdt        |       }t        |       |j                  | j                         g      }|j                  |      S # t
        $ r}dt        |       }t        |      |d}~ww xY w)a  Export a Series via the Arrow PyCapsule Interface.

        Narwhals doesn't implement anything itself here:

        - if the underlying series implements the interface, it'll return that
        - else, it'll call `to_arrow` and then defer to PyArrow's implementation

        See [PyCapsule Interface](https://arrow.apache.org/docs/dev/format/CDataInterface/PyCapsuleInterface.html)
        for more.
        __arrow_c_stream__)requested_schemar   NzOPyArrow>=16.0.0 is required for `Series.__arrow_c_stream__` for object of type )   r   )r'   _native_seriesr&   rG   pyarrowModuleNotFoundErrorr(   r   __version__chunked_arrayto_arrow)r   rH   native_seriespaexcr,   cas          r   rG   zSeries.__arrow_c_stream__   s     ..==="67 33EU3VV	4  (72cdhivdwcxyC%c**Rt}}/0$$6F$GG # 	4cdhivdwcxyC%c*3	4s   B 	C'CCc                .    | j                   j                  S )a  Convert Narwhals series to native series.

        Returns:
            Series of class that user started with.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_to_native(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_native`:

            >>> agnostic_to_native(s_pd)
            0    1
            1    2
            2    3
            dtype: int64

            >>> agnostic_to_native(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
                1
                2
                3
            ]

            >>> agnostic_to_native(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                2,
                3
              ]
            ]
        )r'   rJ   r0   s    r   	to_nativezSeries.to_native   s    h %%444r!   c                v    | j                  | j                  j                  || j                  |                  S )uh	  Set value(s) at given position(s).

        Arguments:
            indices: Position(s) to set items at.
            values: Values to set.

        Returns:
            A new Series with values set at given positions.

        Note:
            This method always returns a new Series, without modifying the original one.
            Using this function in a for-loop is an anti-pattern, we recommend building
            up your positions and values beforehand and doing an update in one go.

            For example, instead of

            ```python
            for i in [1, 3, 2]:
                value = some_function(i)
                s = s.scatter(i, value)
            ```

            prefer

            ```python
            positions = [1, 3, 2]
            values = [some_function(x) for x in positions]
            s = s.scatter(positions, values)
            ```

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoFrameT

            >>> data = {"a": [1, 2, 3], "b": [4, 5, 6]}
            >>> df_pd = pd.DataFrame(data)
            >>> df_pl = pl.DataFrame(data)
            >>> df_pa = pa.table(data)

            We define a library agnostic function:

            >>> def agnostic_scatter(df_native: IntoFrameT) -> IntoFrameT:
            ...     df = nw.from_native(df_native)
            ...     return df.with_columns(df["a"].scatter([0, 1], [999, 888])).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_scatter`:

            >>> agnostic_scatter(df_pd)
                 a  b
            0  999  4
            1  888  5
            2    3  6

            >>> agnostic_scatter(df_pl)
            shape: (3, 2)
            ┌─────┬─────┐
            │ a   ┆ b   │
            │ --- ┆ --- │
            │ i64 ┆ i64 │
            ╞═════╪═════╡
            │ 999 ┆ 4   │
            │ 888 ┆ 5   │
            │ 3   ┆ 6   │
            └─────┴─────┘

            >>> agnostic_scatter(df_pa)
            pyarrow.Table
            a: int64
            b: int64
            ----
            a: [[999,888,3]]
            b: [[4,5,6]]
        )rC   r'   scatter_extract_native)r   indicesvaluess      r   rW   zSeries.scatter  s9    \ **""**7D4H4H4PQ
 	
r!   c                .    | j                   j                  S )a  Get the shape of the Series.

        Returns:
            A tuple containing the length of the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_shape(s_native: IntoSeries) -> tuple[int]:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.shape

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_shape`:

            >>> agnostic_shape(s_pd)
            (3,)

            >>> agnostic_shape(s_pl)
            (3,)

            >>> agnostic_shape(s_pa)
            (3,)
        )r'   shaper0   s    r   r\   zSeries.shapeh      J %%+++r!   c                B    ddl m} t        ||      r|j                  S |S )Nr   )r   )narwhals.seriesr   r@   r'   )r   argr   s      r   rX   zSeries._extract_native  s     *c6"(((
r!   c                <    | j                  || j                        S )Nr+   )	__class__r%   r   r*   s     r   rC   zSeries._from_compliant_series  s"    ~~++  
 	
r!   c                     || g|i |S )a  Pipe function call.

        Returns:
            A new Series with the results of the piped function applied.

        Examples:
            >>> import polars as pl
            >>> import pandas as pd
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a function to pipe into:

            >>> def agnostic_pipe(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.pipe(lambda x: x + 2).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_pipe`:

            >>> agnostic_pipe(s_pd)
            0    3
            1    4
            2    5
            dtype: int64

            >>> agnostic_pipe(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               3
               4
               5
            ]

            >>> agnostic_pipe(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                3,
                4,
                5
              ]
            ]
        r8   )r   functionargskwargss       r   pipezSeries.pipe  s    h .t.v..r!   c                R    t        d| j                         j                               S )NzNarwhals Series)r   rU   __repr__r0   s    r   rk   zSeries.__repr__  s     .0@0I0I0KLLr!   c                ,    t        | j                        S r7   lenr'   r0   s    r   __len__zSeries.__len__  s    4))**r!   c                ,    t        | j                        S )a6  Return the number of elements in the Series.

        Null values count towards the total.

        Returns:
            The number of elements in the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, None]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function that computes the len of the series:

            >>> def agnostic_len(s_native: IntoSeries) -> int:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.len()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_len`:

            >>> agnostic_len(s_pd)
            3

            >>> agnostic_len(s_pl)
            3

            >>> agnostic_len(s_pa)
            3
        rm   r0   s    r   rn   z
Series.len  s    L 4))**r!   c                .    | j                   j                  S )a  Get the data type of the Series.

        Returns:
            The data type of the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_dtype(s_native: IntoSeriesT) -> nw.dtypes.DType:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dtype

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_dtype`:

            >>> agnostic_dtype(s_pd)
            Int64

            >>> agnostic_dtype(s_pl)
            Int64

            >>> agnostic_dtype(s_pa)
            Int64
        )r'   r3   r0   s    r   r3   zSeries.dtype   r]   r!   c                .    | j                   j                  S )ao  Get the name of the Series.

        Returns:
            The name of the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data, name="foo")
            >>> s_pl = pl.Series("foo", data)

            We define a library agnostic function:

            >>> def agnostic_name(s_native: IntoSeries) -> str:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.name

            We can then pass any supported library such as pandas or Polars
            to `agnostic_name`:

            >>> agnostic_name(s_pd)
            'foo'

            >>> agnostic_name(s_pl)
            'foo'
        )r'   namer0   s    r   rs   zSeries.name'  s    B %%***r!   T   Fcomspan	half_lifealphaadjustmin_periodsignore_nullsc               d    | j                  | j                  j                  |||||||            S )a  Compute exponentially-weighted moving average.

        !!! warning
            This functionality is considered **unstable**. It may be changed at any point
            without it being considered a breaking change.

        Arguments:
            com: Specify decay in terms of center of mass, $\gamma$, with <br> $\alpha = \frac{1}{1+\gamma}\forall\gamma\geq0$
            span: Specify decay in terms of span, $\theta$, with <br> $\alpha = \frac{2}{\theta + 1} \forall \theta \geq 1$
            half_life: Specify decay in terms of half-life, $\tau$, with <br> $\alpha = 1 - \exp \left\{ \frac{ -\ln(2) }{ \tau } \right\} \forall \tau > 0$
            alpha: Specify smoothing factor alpha directly, $0 < \alpha \leq 1$.
            adjust: Divide by decaying adjustment factor in beginning periods to account for imbalance in relative weightings

                - When `adjust=True` (the default) the EW function is calculated
                  using weights $w_i = (1 - \alpha)^i$
                - When `adjust=False` the EW function is calculated recursively by
                  $$
                  y_0=x_0
                  $$
                  $$
                  y_t = (1 - \alpha)y_{t - 1} + \alpha x_t
                  $$
            min_periods: Minimum number of observations in window required to have a value (otherwise result is null).
            ignore_nulls: Ignore missing values when calculating weights.

                - When `ignore_nulls=False` (default), weights are based on absolute
                  positions.
                  For example, the weights of $x_0$ and $x_2$ used in
                  calculating the final weighted average of $[x_0, None, x_2]$ are
                  $(1-\alpha)^2$ and $1$ if `adjust=True`, and
                  $(1-\alpha)^2$ and $\alpha$ if `adjust=False`.
                - When `ignore_nulls=True`, weights are based
                  on relative positions. For example, the weights of
                  $x_0$ and $x_2$ used in calculating the final weighted
                  average of $[x_0, None, x_2]$ are
                  $1-\alpha$ and $1$ if `adjust=True`,
                  and $1-\alpha$ and $\alpha$ if `adjust=False`.

        Returns:
            Series

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(name="a", data=data)
            >>> s_pl = pl.Series(name="a", values=data)

            We define a library agnostic function:

            >>> def agnostic_ewm_mean(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.ewm_mean(com=1, ignore_nulls=False).to_native()

            We can then pass any supported library such as pandas or Polars
            to `agnostic_ewm_mean`:

            >>> agnostic_ewm_mean(s_pd)
            0    1.000000
            1    1.666667
            2    2.428571
            Name: a, dtype: float64

            >>> agnostic_ewm_mean(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: 'a' [f64]
            [
               1.0
               1.666667
               2.428571
            ]
        ru   )rC   r'   ewm_mean)r   rv   rw   rx   ry   rz   r{   r|   s           r   r~   zSeries.ewm_meanJ  sF    l **""++#') , 

 
	
r!   c                l    t        |       | j                  | j                  j                  |            S )a  Cast between data types.

        Arguments:
            dtype: Data type that the object will be cast into.

        Returns:
            A new Series with the specified data type.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [True, False, True]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_cast(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.cast(nw.Int64).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_cast`:

            >>> agnostic_cast(s_pd)
            0    1
            1    0
            2    1
            dtype: int64

            >>> agnostic_cast(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               1
               0
               1
            ]

            >>> agnostic_cast(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                0,
                1
              ]
            ]
        )r   rC   r'   cast)r   r3   s     r   r   zSeries.cast  s/    n 	**4+A+A+F+Fu+MNNr!   c                l    | j                  | j                  j                         | j                        S )u  Convert to dataframe.

        Returns:
            A DataFrame containing this Series as a single column.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoDataFrame
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2]
            >>> s_pd = pd.Series(data, name="a")
            >>> s_pl = pl.Series("a", data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_to_frame(s_native: IntoSeries) -> IntoDataFrame:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.to_frame().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_frame`:

            >>> agnostic_to_frame(s_pd)
               a
            0  1
            1  2

            >>> agnostic_to_frame(s_pl)
            shape: (2, 1)
            ┌─────┐
            │ a   │
            │ --- │
            │ i64 │
            ╞═════╡
            │ 1   │
            │ 2   │
            └─────┘

            >>> agnostic_to_frame(s_pa)
            pyarrow.Table
            : int64
            ----
            : [[1,2]]
        rb   )r    r'   to_framer%   r0   s    r   r   zSeries.to_frame  s4    d ""++-++  
 	
r!   c                6    | j                   j                         S )a  Convert to list.

        Notes:
            This function converts to Python scalars. It's typically
            more efficient to keep your data in the format native to
            your original dataframe, so we recommend only calling this
            when you absolutely need to.

        Returns:
            A list of Python objects.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_to_list(s_native: IntoSeries):
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.to_list()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_list`:

            >>> agnostic_to_list(s_pd)
            [1, 2, 3]

            >>> agnostic_to_list(s_pl)
            [1, 2, 3]

            >>> agnostic_to_list(s_pa)
            [1, 2, 3]
        )r'   to_listr0   s    r   r   zSeries.to_list  s    T %%--//r!   c                6    | j                   j                         S )a  Reduce this Series to the mean value.

        Returns:
            The average of all elements in the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_mean(s_native: IntoSeries) -> float:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.mean()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_mean`:

            >>> agnostic_mean(s_pd)
            np.float64(2.0)

            >>> agnostic_mean(s_pl)
            2.0

            >>> agnostic_mean(s_pa)
            2.0
        )r'   meanr0   s    r   r   zSeries.meanI  s    H %%**,,r!   c                6    | j                   j                         S )a  Reduce this Series to the median value.

        Notes:
            Results might slightly differ across backends due to differences in the underlying algorithms used to compute the median.

        Returns:
            The median value of all elements in the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [5, 3, 8]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a library agnostic function:

            >>> def agnostic_median(s_native: IntoSeries) -> float:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.median()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_median`:

            >>> agnostic_median(s_pd)
            np.float64(5.0)

            >>> agnostic_median(s_pl)
            5.0

            >>> agnostic_median(s_pa)
            5.0
        )r'   medianr0   s    r   r   zSeries.mediano  s    N %%,,..r!   c                6    | j                   j                         S )a  Calculate the sample skewness of the Series.

        Returns:
            The sample skewness of the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 1, 2, 10, 100]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_skew(s_native: IntoSeries) -> float:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.skew()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_skew`:

            >>> agnostic_skew(s_pd)
            np.float64(1.4724267269058975)

            >>> agnostic_skew(s_pl)
            1.4724267269058975

            >>> agnostic_skew(s_pa)
            1.4724267269058975

        Notes:
            The skewness is a measure of the asymmetry of the probability distribution.
            A perfectly symmetric distribution has a skewness of 0.
        )r'   skewr0   s    r   r   zSeries.skew  s    P %%**,,r!   c                6    | j                   j                         S )a  Returns the number of non-null elements in the Series.

        Returns:
            The number of non-null elements in the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_count(s_native: IntoSeries) -> int:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.count()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_count`:

            >>> agnostic_count(s_pd)
            np.int64(3)

            >>> agnostic_count(s_pl)
            3

            >>> agnostic_count(s_pa)
            3
        )r'   countr0   s    r   r   zSeries.count  s    H %%++--r!   c                6    | j                   j                         S )a[  Return whether any of the values in the Series are True.

        Notes:
          Only works on Series of data type Boolean.

        Returns:
            A boolean indicating if any values in the Series are True.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [False, True, False]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_any(s_native: IntoSeries) -> bool:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.any()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_any`:

            >>> agnostic_any(s_pd)
            np.True_

            >>> agnostic_any(s_pl)
            True

            >>> agnostic_any(s_pa)
            True
        )r'   anyr0   s    r   r   z
Series.any  s    N %%))++r!   c                6    | j                   j                         S )a  Return whether all values in the Series are True.

        Returns:
            A boolean indicating if all values in the Series are True.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [False, True, False]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_all(s_native: IntoSeries) -> bool:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.all()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_all`:

            >>> agnostic_all(s_pd)
            np.False_

            >>> agnostic_all(s_pl)
            False

            >>> agnostic_all(s_pa)
            False
        )r'   allr0   s    r   r   z
Series.all      H %%))++r!   c                6    | j                   j                         S )a  Get the minimal value in this Series.

        Returns:
            The minimum value in the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_min(s_native: IntoSeries):
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.min()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_min`:

            >>> agnostic_min(s_pd)
            np.int64(1)

            >>> agnostic_min(s_pl)
            1

            >>> agnostic_min(s_pa)
            1
        )r'   minr0   s    r   r   z
Series.min7  r   r!   c                6    | j                   j                         S )a  Get the maximum value in this Series.

        Returns:
            The maximum value in the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_max(s_native: IntoSeries):
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.max()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_max`:

            >>> agnostic_max(s_pd)
            np.int64(3)

            >>> agnostic_max(s_pl)
            3

            >>> agnostic_max(s_pa)
            3
        )r'   maxr0   s    r   r   z
Series.max]  r   r!   c                6    | j                   j                         S )a  Returns the index of the minimum value.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_arg_min(s_native: IntoSeries):
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.arg_min()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_arg_min`:

            >>> agnostic_arg_min(s_pd)
            np.int64(0)

            >>> agnostic_arg_min(s_pl)
            0

            >>> agnostic_arg_min(s_pa)
            0
        )r'   arg_minr0   s    r   r   zSeries.arg_min      B %%--//r!   c                6    | j                   j                         S )a  Returns the index of the maximum value.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_arg_max(s_native: IntoSeries):
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.arg_max()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_arg_max`:

            >>> agnostic_arg_max(s_pd)
            np.int64(2)

            >>> agnostic_arg_max(s_pl)
            2

            >>> agnostic_arg_max(s_pa)
            2
        )r'   arg_maxr0   s    r   r   zSeries.arg_max  r   r!   c                6    | j                   j                         S )a  Reduce this Series to the sum value.

        Returns:
            The sum of all elements in the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_sum(s_native: IntoSeries):
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.sum()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_sum`:

            >>> agnostic_sum(s_pd)
            np.int64(6)

            >>> agnostic_sum(s_pl)
            6

            >>> agnostic_sum(s_pa)
            6
        )r'   sumr0   s    r   r   z
Series.sum  r   r!   ddofc               :    | j                   j                  |      S )a  Get the standard deviation of this Series.

        Arguments:
            ddof: "Delta Degrees of Freedom": the divisor used in the calculation is N - ddof,
                     where N represents the number of elements.

        Returns:
            The standard deviation of all elements in the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_std(s_native: IntoSeries) -> float:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.std()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_std`:

            >>> agnostic_std(s_pd)
            np.float64(1.0)

            >>> agnostic_std(s_pl)
            1.0

            >>> agnostic_std(s_pa)
            1.0
        r   )r'   stdr   r   s     r   r   z
Series.std  s    P %%))t)44r!   c               :    | j                   j                  |      S )aS  Get the variance of this Series.

        Arguments:
            ddof: "Delta Degrees of Freedom": the divisor used in the calculation is N - ddof,
                     where N represents the number of elements.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_var(s_native: IntoSeries) -> float:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.var()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_var`:

            >>> agnostic_var(s_pd)
            np.float64(1.0)

            >>> agnostic_var(s_pl)
            1.0

            >>> agnostic_var(s_pa)
            1.0
        r   )r'   varr   s     r   r   z
Series.var  s    J %%))t)44r!   c                    | j                  | j                  j                  | j                  |      | j                  |                  S )a  Clip values in the Series.

        Arguments:
            lower_bound: Lower bound value.
            upper_bound: Upper bound value.

        Returns:
            A new Series with values clipped to the specified bounds.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_clip_lower(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.clip(2).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_clip_lower`:

            >>> agnostic_clip_lower(s_pd)
            0    2
            1    2
            2    3
            dtype: int64

            >>> agnostic_clip_lower(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               2
               2
               3
            ]

            >>> agnostic_clip_lower(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2,
                2,
                3
              ]
            ]

            We define another library agnostic function:

            >>> def agnostic_clip_upper(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.clip(upper_bound=2).to_native()

           We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_clip_upper`:

            >>> agnostic_clip_upper(s_pd)
            0    1
            1    2
            2    2
            dtype: int64

            >>> agnostic_clip_upper(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               1
               2
               2
            ]

            >>> agnostic_clip_upper(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                2,
                2
              ]
            ]

            We can have both at the same time

            >>> data = [-1, 1, -3, 3, -5, 5]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_clip(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.clip(-1, 3).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_clip`:

            >>> agnostic_clip(s_pd)
            0   -1
            1    1
            2   -1
            3    3
            4   -1
            5    3
            dtype: int64

            >>> agnostic_clip(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (6,)
            Series: '' [i64]
            [
               -1
                1
               -1
                3
               -1
                3
            ]

            >>> agnostic_clip_upper(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                -1,
                1,
                -3,
                2,
                -5,
                2
              ]
            ]
        )lower_boundupper_bound)rC   r'   cliprX   )r   r   r   s      r   r   zSeries.clip@  sM    \ **""'' 00= 00= ( 
 	
r!   c                t    | j                  | j                  j                  | j                  |                  S )a;  Check if the elements of this Series are in the other sequence.

        Arguments:
            other: Sequence of primitive type.

        Returns:
            A new Series with boolean values indicating if the elements are in the other sequence.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_is_in(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_in([3, 2, 8]).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_is_in`:

            >>> agnostic_is_in(s_pd)
            0    False
            1     True
            2     True
            dtype: bool

            >>> agnostic_is_in(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [bool]
            [
               false
               true
               true
            ]

            >>> agnostic_is_in(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                false,
                true,
                true
              ]
            ]
        )rC   r'   is_inrX   r   others     r   r   zSeries.is_in  s7    n **""(()=)=e)DE
 	
r!   c                T    | j                  | j                  j                               S )a  Find elements where boolean Series is True.

        Returns:
            A new Series with the indices of elements that are True.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, None, None, 2]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_arg_true(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_null().arg_true().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_arg_true`:

            >>> agnostic_arg_true(s_pd)
            1    1
            2    2
            dtype: int64

            >>> agnostic_arg_true(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [u32]
            [
               1
               2
            ]

            >>> agnostic_arg_true(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                2
              ]
            ]
        )rC   r'   arg_truer0   s    r   r   zSeries.arg_true  s%    b **4+A+A+J+J+LMMr!   c                T    | j                  | j                  j                               S )a  Drop null values.

        Notes:
            pandas handles null values differently from Polars and PyArrow.
            See [null_handling](../pandas_like_concepts/null_handling.md/)
            for reference.

        Returns:
            A new Series with null values removed.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [2, 4, None, 3, 5]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_drop_nulls(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.drop_nulls().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_drop_nulls`:

            >>> agnostic_drop_nulls(s_pd)
            0    2.0
            1    4.0
            3    3.0
            4    5.0
            dtype: float64

            >>> agnostic_drop_nulls(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [i64]
            [
                2
                4
                3
                5
            ]

            >>> agnostic_drop_nulls(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2,
                4,
                3,
                5
              ]
            ]
        )rC   r'   
drop_nullsr0   s    r   r   zSeries.drop_nullsC  s%    x **4+A+A+L+L+NOOr!   c                T    | j                  | j                  j                               S )a  Calculate the absolute value of each element.

        Returns:
            A new Series with the absolute values of the original elements.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [2, -4, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_abs(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.abs().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_abs`:

            >>> agnostic_abs(s_pd)
            0    2
            1    4
            2    3
            dtype: int64

            >>> agnostic_abs(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               2
               4
               3
            ]

            >>> agnostic_abs(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2,
                4,
                3
              ]
            ]
        )rC   r'   absr0   s    r   r   z
Series.abs  s%    h **4+A+A+E+E+GHHr!   reversec               X    | j                  | j                  j                  |            S )a  Calculate the cumulative sum.

        Arguments:
            reverse: reverse the operation

        Returns:
            A new Series with the cumulative sum of non-null values.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [2, 4, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_cum_sum(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.cum_sum().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_cum_sum`:

            >>> agnostic_cum_sum(s_pd)
            0    2
            1    6
            2    9
            dtype: int64

            >>> agnostic_cum_sum(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               2
               6
               9
            ]

            >>> agnostic_cum_sum(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2,
                6,
                9
              ]
            ]
        r   )rC   r'   cum_sumr   r   s     r   r   zSeries.cum_sum  s/    n **""**7*;
 	
r!   maintain_orderc               X    | j                  | j                  j                  |            S )a  Returns unique values of the series.

        Arguments:
            maintain_order: Keep the same order as the original series. This may be more
                expensive to compute. Settings this to `True` blocks the possibility
                to run on the streaming engine for Polars.

        Returns:
            A new Series with duplicate values removed.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [2, 4, 4, 6]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_unique(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.unique(maintain_order=True).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_unique`:

            >>> agnostic_unique(s_pd)
            0    2
            1    4
            2    6
            dtype: int64

            >>> agnostic_unique(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               2
               4
               6
            ]

            >>> agnostic_unique(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2,
                4,
                6
              ]
            ]
        r   )rC   r'   unique)r   r   s     r   r   zSeries.unique  s/    r **"")))H
 	
r!   c                T    | j                  | j                  j                               S )av  Calculate the difference with the previous element, for each element.

        Notes:
            pandas may change the dtype here, for example when introducing missing
            values in an integer column. To ensure, that the dtype doesn't change,
            you may want to use `fill_null` and `cast`. For example, to calculate
            the diff and fill missing values with `0` in a Int64 column, you could
            do:

                s.diff().fill_null(0).cast(nw.Int64)

        Returns:
            A new Series with the difference between each element and its predecessor.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [2, 4, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_diff(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.diff().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_diff`:

            >>> agnostic_diff(s_pd)
            0    NaN
            1    2.0
            2   -1.0
            dtype: float64

            >>> agnostic_diff(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               null
               2
               -1
            ]

            >>> agnostic_diff(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                null,
                2,
                -1
              ]
            ]
        )rC   r'   diffr0   s    r   r   zSeries.diff/  s%    z **4+A+A+F+F+HIIr!   c                V    | j                  | j                  j                  |            S )a  Shift values by `n` positions.

        Arguments:
            n: Number of indices to shift forward. If a negative value is passed,
                values are shifted in the opposite direction instead.

        Returns:
            A new Series with values shifted by n positions.

        Notes:
            pandas may change the dtype here, for example when introducing missing
            values in an integer column. To ensure, that the dtype doesn't change,
            you may want to use `fill_null` and `cast`. For example, to shift
            and fill missing values with `0` in a Int64 column, you could
            do:

                s.shift(1).fill_null(0).cast(nw.Int64)

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [2, 4, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_shift(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.shift(1).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_shift`:

            >>> agnostic_shift(s_pd)
            0    NaN
            1    2.0
            2    4.0
            dtype: float64

            >>> agnostic_shift(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               null
               2
               4
            ]

            >>> agnostic_shift(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                null,
                2,
                4
              ]
            ]
        )rC   r'   shiftr   ns     r   r   zSeries.shiftn  s'    B **4+A+A+G+G+JKKr!   )fractionwith_replacementseedc               ^    | j                  | j                  j                  ||||            S )aR  Sample randomly from this Series.

        Arguments:
            n: Number of items to return. Cannot be used with fraction.
            fraction: Fraction of items to return. Cannot be used with n.
            with_replacement: Allow values to be sampled more than once.
            seed: Seed for the random number generator. If set to None (default), a random
                seed is generated for each sample operation.

        Returns:
            A new Series containing randomly sampled values from the original Series.

        Notes:
            The `sample` method returns a Series with a specified number of
            randomly selected items chosen from this Series.
            The results are not consistent across libraries.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3, 4]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_sample(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.sample(fraction=1.0, with_replacement=True).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_sample`:

            >>> agnostic_sample(s_pd)  # doctest: +SKIP
               a
            2  3
            1  2
            3  4
            3  4

            >>> agnostic_sample(s_pl)  # doctest: +SKIP
            shape: (4,)
            Series: '' [i64]
            [
               1
               4
               3
               4
            ]

            >>> agnostic_sample(s_pa)  # doctest: +SKIP
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                4,
                3,
                4
              ]
            ]
        )r   r   r   r   )rC   r'   sample)r   r   r   r   r   s        r   r   zSeries.sample  s<    T **""))h9IPT * 
 	
r!   c                X    | j                  | j                  j                  |            S )a  Rename the Series.

        Notes:
            This method is very cheap, but does not guarantee that data
            will be copied. For example:

            ```python
            s1: nw.Series
            s2 = s1.alias("foo")
            arr = s2.to_numpy()
            arr[0] = 999
            ```

            may (depending on the backend, and on the version) result in
            `s1`'s data being modified. We recommend:

                - if you need to alias an object and don't need the original
                  one around any more, just use `alias` without worrying about it.
                - if you were expecting `alias` to copy data, then explicily call
                  `.clone` before calling `alias`.

        Arguments:
            name: The new name.

        Returns:
            A new Series with the updated name.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data, name="foo")
            >>> s_pl = pl.Series("foo", data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_alias(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.alias("bar").to_native()

            We can then pass any supported library such as pandas or Polars, or
            PyArrow to `agnostic_alias`:

            >>> agnostic_alias(s_pd)
            0    1
            1    2
            2    3
            Name: bar, dtype: int64

            >>> agnostic_alias(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: 'bar' [i64]
            [
               1
               2
               3
            ]

            >>> agnostic_alias(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at 0x...>
            [
              [
                1,
                2,
                3
              ]
            ]
        rs   )rC   r'   aliasr   rs   s     r   r   zSeries.alias  s*    T **4+A+A+G+GT+G+RSSr!   c                &    | j                  |      S )a  Rename the Series.

        Alias for `Series.alias()`.

        Notes:
            This method is very cheap, but does not guarantee that data
            will be copied. For example:

            ```python
            s1: nw.Series
            s2 = s1.rename("foo")
            arr = s2.to_numpy()
            arr[0] = 999
            ```

            may (depending on the backend, and on the version) result in
            `s1`'s data being modified. We recommend:

                - if you need to rename an object and don't need the original
                  one around any more, just use `rename` without worrying about it.
                - if you were expecting `rename` to copy data, then explicily call
                  `.clone` before calling `rename`.

        Arguments:
            name: The new name.

        Returns:
            A new Series with the updated name.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data, name="foo")
            >>> s_pl = pl.Series("foo", data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_rename(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.rename("bar").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_rename`:

            >>> agnostic_rename(s_pd)
            0    1
            1    2
            2    3
            Name: bar, dtype: int64

            >>> agnostic_rename(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: 'bar' [i64]
            [
               1
               2
               3
            ]

            >>> agnostic_rename(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at 0x...>
            [
              [
                1,
                2,
                3
              ]
            ]
        r   )r   r   s     r   renamezSeries.renameM  s    X zztz$$r!   return_dtypec                   |Ot        |t              sd}t        |      t        |j	                               }t        |j                               }| j                  | j                  j                  |||            S )a<	  Replace all values by different values.

        This function must replace all non-null input values (else it raises an error).

        Arguments:
            old: Sequence of values to replace. It also accepts a mapping of values to
                their replacement as syntactic sugar for
                `replace_all(old=list(mapping.keys()), new=list(mapping.values()))`.
            new: Sequence of values to replace by. Length must match the length of `old`.
            return_dtype: The data type of the resulting expression. If set to `None`
                (default), the data type is determined automatically based on the other
                inputs.

        Returns:
            A new Series with values replaced according to the mapping.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = {"a": [3, 0, 1, 2]}
            >>> df_pd = pd.DataFrame(data)
            >>> df_pl = pl.DataFrame(data)
            >>> df_pa = pa.table(data)

            Let's define dataframe-agnostic functions:

            >>> def agnostic_replace_strict(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.replace_strict(
            ...         [0, 1, 2, 3], ["zero", "one", "two", "three"], return_dtype=nw.String
            ...     ).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_replace_strict`:

            >>> agnostic_replace_strict(df_pd["a"])
            0    three
            1     zero
            2      one
            3      two
            Name: a, dtype: object

            >>> agnostic_replace_strict(df_pl["a"])  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: 'a' [str]
            [
                "three"
                "zero"
                "one"
                "two"
            ]

            >>> agnostic_replace_strict(df_pa["a"])
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "three",
                "zero",
                "one",
                "two"
              ]
            ]
        zB`new` argument is required if `old` argument is not a Mapping typer   )	r@   r
   	TypeErrorlistrZ   keysrC   r'   replace_strict)r   oldnewr   r,   s        r   r   zSeries.replace_strict  sq    T ;c7+Zn$szz|$Csxxz"C**""11#s1V
 	
r!   
descending
nulls_lastc               Z    | j                  | j                  j                  ||            S )a	  Sort this Series. Place null values first.

        Arguments:
            descending: Sort in descending order.
            nulls_last: Place null values last instead of first.

        Returns:
            A new sorted Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [5, None, 1, 2]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define library agnostic functions:

            >>> def agnostic_sort(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.sort().to_native()

            >>> def agnostic_sort_descending(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.sort(descending=True).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_sort` and `agnostic_sort_descending`:

            >>> agnostic_sort(s_pd)
            1    NaN
            2    1.0
            3    2.0
            0    5.0
            dtype: float64

            >>> agnostic_sort(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [i64]
            [
               null
               1
               2
               5
            ]

            >>> agnostic_sort(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                null,
                1,
                2,
                5
              ]
            ]

            >>> agnostic_sort_descending(s_pd)
            1    NaN
            0    5.0
            3    2.0
            2    1.0
            dtype: float64

            >>> agnostic_sort_descending(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [i64]
            [
               null
               5
               2
               1
            ]

            >>> agnostic_sort_descending(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                null,
                5,
                2,
                1
              ]
            ]
        r   )rC   r'   sort)r   r   r   s      r   r   zSeries.sort  s1    v **""'':*'U
 	
r!   c                T    | j                  | j                  j                               S )a  Returns a boolean Series indicating which values are null.

        Notes:
            pandas handles null values differently from Polars and PyArrow.
            See [null_handling](../pandas_like_concepts/null_handling.md/)
            for reference.

        Returns:
            A boolean Series indicating which values are null.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, None]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_is_null(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_null().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_is_null`:

            >>> agnostic_is_null(s_pd)
            0    False
            1    False
            2     True
            dtype: bool

            >>> agnostic_is_null(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [bool]
            [
               false
               false
               true
            ]

            >>> agnostic_is_null(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                false,
                false,
                true
              ]
            ]
        )rC   r'   is_nullr0   s    r   r   zSeries.is_nullP	  s%    r **4+A+A+I+I+KLLr!   c                T    | j                  | j                  j                               S )a.  Returns a boolean Series indicating which values are NaN.

        Returns:
            A boolean Series indicating which values are NaN.

        Notes:
            pandas handles null values differently from Polars and PyArrow.
            See [null_handling](../pandas_like_concepts/null_handling.md/)
            for reference.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [0.0, None, 2.0]
            >>> s_pd = pd.Series(data, dtype="Float64")
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data], type=pa.float64())

            >>> def agnostic_self_div_is_nan(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_nan().to_native()

            >>> print(agnostic_self_div_is_nan(s_pd))
            0    False
            1     <NA>
            2    False
            dtype: boolean

            >>> print(agnostic_self_div_is_nan(s_pl))  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [bool]
            [
                    false
                    null
                    false
            ]

            >>> print(agnostic_self_div_is_nan(s_pa))  # doctest: +NORMALIZE_WHITESPACE
            [
              [
                false,
                null,
                false
              ]
            ]
        )rC   r'   is_nanr0   s    r   r   zSeries.is_nan	  s%    f **4+A+A+H+H+JKKr!   c                    ||d}t        |      ||d}t        |      ||dvrd| }t        |      | j                  | j                  j                  |||            S )a  Fill null values using the specified value.

        Arguments:
            value: Value used to fill null values.
            strategy: Strategy used to fill null values.
            limit: Number of consecutive null values to fill when using the 'forward' or 'backward' strategy.

        Notes:
            pandas handles null values differently from Polars and PyArrow.
            See [null_handling](../pandas_like_concepts/null_handling.md/)
            for reference.

        Returns:
            A new Series with null values filled according to the specified value or strategy.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, None]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_fill_null(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.fill_null(5).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_fill_null`:

            >>> agnostic_fill_null(s_pd)
            0    1.0
            1    2.0
            2    5.0
            dtype: float64

            >>> agnostic_fill_null(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               1
               2
               5
            ]

            >>> agnostic_fill_null(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                2,
                5
              ]
            ]

            Using a strategy:

            >>> def agnostic_fill_null_with_strategy(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.fill_null(strategy="forward", limit=1).to_native()

            >>> agnostic_fill_null_with_strategy(s_pd)
            0    1.0
            1    2.0
            2    2.0
            dtype: float64

            >>> agnostic_fill_null_with_strategy(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               1
               2
               2
            ]

            >>> agnostic_fill_null_with_strategy(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                2,
                2
              ]
            ]
        z*cannot specify both `value` and `strategy`z0must specify either a fill `value` or `strategy`>   forwardbackwardzstrategy not supported: )valuestrategylimit)
ValueErrorrC   r'   	fill_null)r   r   r   r   r,   s        r   r   zSeries.fill_null	  s    D !5>CS/!=X-DCS/!H4K$K,XJ7CS/!**"",,58SX,Y
 	
r!   c                    | j                  | j                  j                  | j                  |      | j                  |      |            S )a  Get a boolean mask of the values that are between the given lower/upper bounds.

        Arguments:
            lower_bound: Lower bound value.
            upper_bound: Upper bound value.
            closed: Define which sides of the interval are closed (inclusive).

        Notes:
            If the value of the `lower_bound` is greater than that of the `upper_bound`,
            then the values will be False, as no value can satisfy the condition.

        Returns:
            A boolean Series indicating which values are between the given bounds.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3, 4, 5]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_is_between(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_between(2, 4, "right").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_is_between`:

            >>> agnostic_is_between(s_pd)
            0    False
            1    False
            2     True
            3     True
            4    False
            dtype: bool

            >>> agnostic_is_between(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (5,)
            Series: '' [bool]
            [
               false
               false
               true
               true
               false
            ]

            >>> agnostic_is_between(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                false,
                false,
                true,
                true,
                false
              ]
            ]
        )closed)rC   r'   
is_betweenrX   )r   r   r   r   s       r   r   zSeries.is_between/
  sP    J **""--$$[1$$[1 . 
 	
r!   c                6    | j                   j                         S )a  Count the number of unique values.

        Returns:
            Number of unique values in the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_n_unique(s_native: IntoSeries) -> int:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.n_unique()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_n_unique`:

            >>> agnostic_n_unique(s_pd)
            3

            >>> agnostic_n_unique(s_pl)
            3

            >>> agnostic_n_unique(s_pa)
            3
        )r'   n_uniquer0   s    r   r   zSeries.n_unique|
  s    H %%..00r!   c                6    | j                   j                         S )aT  Convert to numpy.

        Returns:
            NumPy ndarray representation of the Series.

        Examples:
            >>> import numpy as np
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data, name="a")
            >>> s_pl = pl.Series("a", data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_to_numpy(s_native: IntoSeries) -> np.ndarray:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.to_numpy()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_numpy`:

            >>> agnostic_to_numpy(s_pd)
            array([1, 2, 3]...)

            >>> agnostic_to_numpy(s_pl)
            array([1, 2, 3]...)

            >>> agnostic_to_numpy(s_pa)
            array([1, 2, 3]...)
        )r'   to_numpyr0   s    r   r   zSeries.to_numpy
      J %%..00r!   c                6    | j                   j                         S )a  Convert to pandas.

        Returns:
            A pandas Series containing the data from this Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data, name="a")
            >>> s_pl = pl.Series("a", data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_to_pandas(s_native: IntoSeries) -> pd.Series:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.to_pandas()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_pandas`:

            >>> agnostic_to_pandas(s_pd)
            0    1
            1    2
            2    3
            Name: a, dtype: int64

            >>> agnostic_to_pandas(s_pl)
            0    1
            1    2
            2    3
            Name: a, dtype: int64

            >>> agnostic_to_pandas(s_pa)
            0    1
            1    2
            2    3
            Name: , dtype: int64
        )r'   	to_pandasr0   s    r   r   zSeries.to_pandas
  s    Z %%//11r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __add__rX   r   s     r   r   zSeries.__add__
  4    **""**4+?+?+FG
 	
r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __radd__rX   r   s     r   r   zSeries.__radd__
  4    **""++D,@,@,GH
 	
r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __sub__rX   r   s     r   r   zSeries.__sub__  r   r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __rsub__rX   r   s     r   r   zSeries.__rsub__  r   r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __mul__rX   r   s     r   r   zSeries.__mul__  r   r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __rmul__rX   r   s     r   r   zSeries.__rmul__  r   r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __truediv__rX   r   s     r   r   zSeries.__truediv__  s4    **""..t/C/CE/JK
 	
r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __rtruediv__rX   r   s     r   r  zSeries.__rtruediv__  4    **""//0D0DU0KL
 	
r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __floordiv__rX   r   s     r   r  zSeries.__floordiv__   r  r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __rfloordiv__rX   r   s     r   r  zSeries.__rfloordiv__%  s4    **""001E1Ee1LM
 	
r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __pow__rX   r   s     r   r  zSeries.__pow__*  r   r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __rpow__rX   r   s     r   r
  zSeries.__rpow__/  r   r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __mod__rX   r   s     r   r  zSeries.__mod__4  r   r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __rmod__rX   r   s     r   r  zSeries.__rmod__9  r   r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __eq__rX   r   s     r   r  zSeries.__eq__>  4    **""))$*>*>u*EF
 	
r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __ne__rX   r   s     r   r  zSeries.__ne__C  r  r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __gt__rX   r   s     r   r  zSeries.__gt__H  r  r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __ge__rX   r   s     r   r  zSeries.__ge__M  r  r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __lt__rX   r   s     r   r  zSeries.__lt__R  r  r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __le__rX   r   s     r   r  zSeries.__le__W  r  r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __and__rX   r   s     r   r  zSeries.__and__\  r   r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __rand__rX   r   s     r   r  zSeries.__rand__a  r   r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __or__rX   r   s     r   r!  zSeries.__or__f  r  r!   c                t    | j                  | j                  j                  | j                  |                  S r7   )rC   r'   __ror__rX   r   s     r   r#  zSeries.__ror__k  r   r!   c                T    | j                  | j                  j                               S r7   )rC   r'   
__invert__r0   s    r   r%  zSeries.__invert__q  s"    **4+A+A+L+L+NOOr!   c                t    | j                  | j                  j                  | j                  |                  S )a  Filter elements in the Series based on a condition.

        Returns:
            A new Series with elements that satisfy the condition.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [4, 10, 15, 34, 50]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_filter(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.filter(s > 10).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_filter`:

            >>> agnostic_filter(s_pd)
            2    15
            3    34
            4    50
            dtype: int64

            >>> agnostic_filter(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               15
               34
               50
            ]

            >>> agnostic_filter(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                15,
                34,
                50
              ]
            ]
        )rC   r'   filterrX   r   s     r   r'  zSeries.filtert  s7    h **""))$*>*>u*EF
 	
r!   c                T    | j                  | j                  j                               S )aE  Get a mask of all duplicated rows in the Series.

        Returns:
            A new Series with boolean values indicating duplicated rows.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3, 1]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_is_duplicated(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_duplicated().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_is_duplicated`:

            >>> agnostic_is_duplicated(s_pd)
            0     True
            1    False
            2    False
            3     True
            dtype: bool

            >>> agnostic_is_duplicated(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [bool]
            [
                true
                false
                false
                true
            ]

            >>> agnostic_is_duplicated(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                true,
                false,
                false,
                true
              ]
            ]
        )rC   r'   is_duplicatedr0   s    r   r)  zSeries.is_duplicated  s%    n **4+A+A+O+O+QRRr!   c                6    | j                   j                         S )ap  Check if the series is empty.

        Returns:
            A boolean indicating if the series is empty.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            Let's define a dataframe-agnostic function that filters rows in which "foo"
            values are greater than 10, and then checks if the result is empty or not:

            >>> def agnostic_is_empty(s_native: IntoSeries) -> bool:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.filter(s > 10).is_empty()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_is_empty`:

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])
            >>> agnostic_is_empty(s_pd), agnostic_is_empty(s_pl), agnostic_is_empty(s_pa)
            (True, True, True)

            >>> data = [100, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])
            >>> agnostic_is_empty(s_pd), agnostic_is_empty(s_pl), agnostic_is_empty(s_pa)
            (False, False, False)
        )r'   is_emptyr0   s    r   r+  zSeries.is_empty  r   r!   c                T    | j                  | j                  j                               S )a&  Get a mask of all unique rows in the Series.

        Returns:
            A new Series with boolean values indicating unique rows.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3, 1]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_is_unique(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_unique().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_is_unique`:

            >>> agnostic_is_unique(s_pd)
            0    False
            1     True
            2     True
            3    False
            dtype: bool

            >>> agnostic_is_unique(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [bool]
            [
                false
                 true
                 true
                false
            ]
            >>> agnostic_is_unique(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                false,
                true,
                true,
                false
              ]
            ]
        )rC   r'   	is_uniquer0   s    r   r-  zSeries.is_unique  s%    l **4+A+A+K+K+MNNr!   c                6    | j                   j                         S )a$  Create a new Series that shows the null counts per column.

        Notes:
            pandas handles null values differently from Polars and PyArrow.
            See [null_handling](../pandas_like_concepts/null_handling.md/)
            for reference.

        Returns:
            The number of null values in the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, None, None]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function that returns the null count of
            the series:

            >>> def agnostic_null_count(s_native: IntoSeries) -> int:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.null_count()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_null_count`:

            >>> agnostic_null_count(s_pd)
            np.int64(2)

            >>> agnostic_null_count(s_pl)
            2

            >>> agnostic_null_count(s_pa)
            2
        )r'   
null_countr0   s    r   r/  zSeries.null_countE  s    T %%0022r!   c                T    | j                  | j                  j                               S )a  Return a boolean mask indicating the first occurrence of each distinct value.

        Returns:
            A new Series with boolean values indicating the first occurrence of each distinct value.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 1, 2, 3, 2]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_is_first_distinct(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_first_distinct().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_is_first_distinct`:

            >>> agnostic_is_first_distinct(s_pd)
            0     True
            1    False
            2     True
            3     True
            4    False
            dtype: bool

            >>> agnostic_is_first_distinct(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (5,)
            Series: '' [bool]
            [
                true
                false
                true
                true
                false
            ]

            >>> agnostic_is_first_distinct(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                true,
                false,
                true,
                true,
                false
              ]
            ]
        )rC   r'   is_first_distinctr0   s    r   r1  zSeries.is_first_distinctq  s%    t **4+A+A+S+S+UVVr!   c                T    | j                  | j                  j                               S )a  Return a boolean mask indicating the last occurrence of each distinct value.

        Returns:
            A new Series with boolean values indicating the last occurrence of each distinct value.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 1, 2, 3, 2]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_is_last_distinct(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_last_distinct().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_is_last_distinct`:

            >>> agnostic_is_last_distinct(s_pd)
            0    False
            1     True
            2    False
            3     True
            4     True
            dtype: bool

            >>> agnostic_is_last_distinct(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (5,)
            Series: '' [bool]
            [
                false
                true
                false
                true
                true
            ]

            >>> agnostic_is_last_distinct(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                false,
                true,
                false,
                true,
                true
              ]
            ]
        )rC   r'   is_last_distinctr0   s    r   r3  zSeries.is_last_distinct  s%    t **4+A+A+R+R+TUUr!   r   c               :    | j                   j                  |      S )a  Check if the Series is sorted.

        Arguments:
            descending: Check if the Series is sorted in descending order.

        Returns:
            A boolean indicating if the Series is sorted.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> unsorted_data = [1, 3, 2]
            >>> sorted_data = [3, 2, 1]

            Let's define a dataframe-agnostic function:

            >>> def agnostic_is_sorted(s_native: IntoSeries, descending: bool = False):
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_sorted(descending=descending)

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_is_sorted`:

            >>> agnostic_is_sorted(pd.Series(unsorted_data))
            False

            >>> agnostic_is_sorted(pd.Series(sorted_data), descending=True)
            True

            >>> agnostic_is_sorted(pl.Series(unsorted_data))
            False

            >>> agnostic_is_sorted(pl.Series(sorted_data), descending=True)
            True

            >>> agnostic_is_sorted(pa.chunked_array([unsorted_data]))
            False

            >>> agnostic_is_sorted(pa.chunked_array([sorted_data]), descending=True)
            True
        r4  )r'   	is_sorted)r   r   s     r   r6  zSeries.is_sorted  s    \ %%//:/FFr!   r   parallelrs   	normalizec               v    | j                  | j                  j                  ||||      | j                        S )uq	  Count the occurrences of unique values.

        Arguments:
            sort: Sort the output by count in descending order. If set to False (default),
                the order of the output is random.
            parallel: Execute the computation in parallel. Used for Polars only.
            name: Give the resulting count column a specific name; if `normalize` is True
                defaults to "proportion", otherwise defaults to "count".
            normalize: If true gives relative frequencies of the unique values

        Returns:
            A DataFrame with two columns:
            - The original values as first column
            - Either count or proportion as second column, depending on normalize parameter.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoDataFrame
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 1, 2, 3, 2]
            >>> s_pd = pd.Series(data, name="s")
            >>> s_pl = pl.Series(values=data, name="s")
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_value_counts(s_native: IntoSeries) -> IntoDataFrame:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.value_counts(sort=True).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_value_counts`:

            >>> agnostic_value_counts(s_pd)
               s  count
            0  1      2
            1  2      2
            2  3      1

            >>> agnostic_value_counts(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3, 2)
            ┌─────┬───────┐
            │ s   ┆ count │
            │ --- ┆ ---   │
            │ i64 ┆ u32   │
            ╞═════╪═══════╡
            │ 1   ┆ 2     │
            │ 2   ┆ 2     │
            │ 3   ┆ 1     │
            └─────┴───────┘

            >>> agnostic_value_counts(s_pa)
            pyarrow.Table
            : int64
            count: int64
            ----
            : [[1,2,3]]
            count: [[2,2,1]]
        r7  rb   )r    r'   value_countsr%   )r   r   r8  rs   r9  s        r   r;  zSeries.value_counts  sF    N ""//H49 0  ++	  
 	
r!   c                <    | j                   j                  ||      S )a  Get quantile value of the series.

        Note:
            pandas and Polars may have implementation differences for a given interpolation method.

        Arguments:
            quantile: Quantile between 0.0 and 1.0.
            interpolation: Interpolation method.

        Returns:
            The quantile value.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = list(range(50))
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_quantile(s_native: IntoSeries) -> list[float]:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return [
            ...         s.quantile(quantile=q, interpolation="nearest")
            ...         for q in (0.1, 0.25, 0.5, 0.75, 0.9)
            ...     ]

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_quantile`:

            >>> agnostic_quantile(s_pd)
            [np.int64(5), np.int64(12), np.int64(24), np.int64(37), np.int64(44)]

            >>> agnostic_quantile(s_pl)
            [5.0, 12.0, 25.0, 37.0, 44.0]

            >>> agnostic_quantile(s_pa)
            [5, 12, 24, 37, 44]
        )quantileinterpolation)r'   r=  )r   r=  r>  s      r   r=  zSeries.quantileg  s(    d %%..] / 
 	
r!   c                    | j                  | j                  j                  | j                  |      | j                  |                  S )a	  Take values from self or other based on the given mask.

        Where mask evaluates true, take values from self. Where mask evaluates false,
        take values from other.

        Arguments:
            mask: Boolean Series
            other: Series of same type.

        Returns:
            A new Series with values selected from self or other based on the mask.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3, 4, 5]
            >>> other = [5, 4, 3, 2, 1]
            >>> mask = [True, False, True, False, True]

            Let's define a dataframe-agnostic function:

            >>> def agnostic_zip_with(
            ...     s1_native: IntoSeriesT, mask_native: IntoSeriesT, s2_native: IntoSeriesT
            ... ) -> IntoSeriesT:
            ...     s1 = nw.from_native(s1_native, series_only=True)
            ...     mask = nw.from_native(mask_native, series_only=True)
            ...     s2 = nw.from_native(s2_native, series_only=True)
            ...     return s1.zip_with(mask, s2).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_zip_with`:

            >>> agnostic_zip_with(
            ...     s1_native=pl.Series(data),
            ...     mask_native=pl.Series(mask),
            ...     s2_native=pl.Series(other),
            ... )  # doctest: +NORMALIZE_WHITESPACE
            shape: (5,)
            Series: '' [i64]
            [
               1
               4
               3
               2
               5
            ]

            >>> agnostic_zip_with(
            ...     s1_native=pd.Series(data),
            ...     mask_native=pd.Series(mask),
            ...     s2_native=pd.Series(other),
            ... )
            0    1
            1    4
            2    3
            3    2
            4    5
            dtype: int64

            >>> agnostic_zip_with(
            ...     s1_native=pa.chunked_array([data]),
            ...     mask_native=pa.chunked_array([mask]),
            ...     s2_native=pa.chunked_array([other]),
            ... )  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                4,
                3,
                2,
                5
              ]
            ]
        )rC   r'   zip_withrX   )r   maskr   s      r   r@  zSeries.zip_with  sG    ` **""++$$T*D,@,@,G
 	
r!   c                :    | j                   j                  |      S )a  Return the Series as a scalar, or return the element at the given index.

        If no index is provided, this is equivalent to `s[0]`, with a check
        that the shape is (1,). With an index, this is equivalent to `s[index]`.

        Returns:
            The scalar value of the Series or the element at the given index.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            Let's define a dataframe-agnostic function that returns item at given index

            >>> def agnostic_item(s_native: IntoSeries, index=None):
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.item(index)

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_item`:

            >>> (
            ...     agnostic_item(pl.Series("a", [1]), None),
            ...     agnostic_item(pd.Series([1]), None),
            ...     agnostic_item(pa.chunked_array([[1]]), None),
            ... )
            (1, np.int64(1), 1)

            >>> (
            ...     agnostic_item(pl.Series("a", [9, 8, 7]), -1),
            ...     agnostic_item(pl.Series([9, 8, 7]), -2),
            ...     agnostic_item(pa.chunked_array([[9, 8, 7]]), -3),
            ... )
            (7, 8, 9)
        )index)r'   item)r   rC  s     r   rD  zSeries.item  s    N %%***77r!   c                V    | j                  | j                  j                  |            S )a  Get the first `n` rows.

        Arguments:
            n: Number of rows to return.

        Returns:
            A new Series containing the first n characters of each string.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = list(range(10))
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function that returns the first 3 rows:

            >>> def agnostic_head(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.head(3).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_head`:

            >>> agnostic_head(s_pd)
            0    0
            1    1
            2    2
            dtype: int64

            >>> agnostic_head(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               0
               1
               2
            ]

            >>> agnostic_head(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                0,
                1,
                2
              ]
            ]
        )rC   r'   headr   s     r   rF  zSeries.head  '    n **4+A+A+F+Fq+IJJr!   c                V    | j                  | j                  j                  |            S )a  Get the last `n` rows.

        Arguments:
            n: Number of rows to return.

        Returns:
            A new Series with the last n rows.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = list(range(10))
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function that returns the last 3 rows:

            >>> def agnostic_tail(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.tail(3).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_tail`:

            >>> agnostic_tail(s_pd)
            7    7
            8    8
            9    9
            dtype: int64

            >>> agnostic_tail(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
               7
               8
               9
            ]

            >>> agnostic_tail(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                7,
                8,
                9
              ]
            ]
        )rC   r'   tailr   s     r   rI  zSeries.tailU  rG  r!   c                V    | j                  | j                  j                  |            S )a  Round underlying floating point data by `decimals` digits.

        Arguments:
            decimals: Number of decimals to round by.

        Returns:
            A new Series with rounded values.

        Notes:
            For values exactly halfway between rounded decimal values pandas behaves differently than Polars and Arrow.

            pandas rounds to the nearest even value (e.g. -0.5 and 0.5 round to 0.0, 1.5 and 2.5 round to 2.0, 3.5 and
            4.5 to 4.0, etc..).

            Polars and Arrow round away from 0 (e.g. -0.5 to -1.0, 0.5 to 1.0, 1.5 to 2.0, 2.5 to 3.0, etc..).

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1.12345, 2.56789, 3.901234]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function that rounds to the first decimal:

            >>> def agnostic_round(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.round(1).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_round`:

            >>> agnostic_round(s_pd)
            0    1.1
            1    2.6
            2    3.9
            dtype: float64

            >>> agnostic_round(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [f64]
            [
               1.1
               2.6
               3.9
            ]

            >>> agnostic_round(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1.1,
                2.6,
                3.9
              ]
            ]
        )rC   r'   round)r   decimalss     r   rK  zSeries.round  s'    ~ **4+A+A+G+G+QRRr!   _	separator
drop_firstc               r    | j                  | j                  j                  ||      | j                        S )u  Get dummy/indicator variables.

        Arguments:
            separator: Separator/delimiter used when generating column names.
            drop_first: Remove the first category from the variable being encoded.

        Returns:
            A new DataFrame containing the dummy/indicator variables.

        Notes:
            pandas and Polars handle null values differently. Polars distinguishes
            between NaN and Null, whereas pandas doesn't.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoDataFrame
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3]
            >>> s_pd = pd.Series(data, name="a")
            >>> s_pl = pl.Series("a", data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_to_dummies(
            ...     s_native: IntoSeries, drop_first: bool = False
            ... ) -> IntoDataFrame:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.to_dummies(drop_first=drop_first).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_dummies`:

            >>> agnostic_to_dummies(s_pd)
               a_1  a_2  a_3
            0    1    0    0
            1    0    1    0
            2    0    0    1

            >>> agnostic_to_dummies(s_pd, drop_first=True)
               a_2  a_3
            0    0    0
            1    1    0
            2    0    1

            >>> agnostic_to_dummies(s_pl)
            shape: (3, 3)
            ┌─────┬─────┬─────┐
            │ a_1 ┆ a_2 ┆ a_3 │
            │ --- ┆ --- ┆ --- │
            │ i8  ┆ i8  ┆ i8  │
            ╞═════╪═════╪═════╡
            │ 1   ┆ 0   ┆ 0   │
            │ 0   ┆ 1   ┆ 0   │
            │ 0   ┆ 0   ┆ 1   │
            └─────┴─────┴─────┘

            >>> agnostic_to_dummies(s_pl, drop_first=True)
            shape: (3, 2)
            ┌─────┬─────┐
            │ a_2 ┆ a_3 │
            │ --- ┆ --- │
            │ i8  ┆ i8  │
            ╞═════╪═════╡
            │ 0   ┆ 0   │
            │ 1   ┆ 0   │
            │ 0   ┆ 1   │
            └─────┴─────┘

            >>> agnostic_to_dummies(s_pa)
            pyarrow.Table
            _1: int8
            _2: int8
            _3: int8
            ----
            _1: [[1,0,0]]
            _2: [[0,1,0]]
            _3: [[0,0,1]]
            >>> agnostic_to_dummies(s_pa, drop_first=True)
            pyarrow.Table
            _2: int8
            _3: int8
            ----
            _2: [[0,1,0]]
            _3: [[0,0,1]]
        rN  rb   )r    r'   
to_dummiesr%   )r   rO  rP  s      r   rR  zSeries.to_dummies  s;    z ""--	j-Y++  
 	
r!   c                Z    | j                  | j                  j                  ||            S )a]  Take every nth value in the Series and return as new Series.

        Arguments:
            n: Gather every *n*-th row.
            offset: Starting index.

        Returns:
            A new Series with every nth value starting from the offset.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 2, 3, 4]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function in which gather every 2 rows,
            starting from a offset of 1:

            >>> def agnostic_gather_every(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.gather_every(n=2, offset=1).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_gather_every`:

            >>> agnostic_gather_every(s_pd)
            1    2
            3    4
            dtype: int64

            >>> agnostic_gather_every(s_pl)  # doctest:+NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i64]
            [
               2
               4
            ]

            >>> agnostic_gather_every(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2,
                4
              ]
            ]
        )r   offset)rC   r'   gather_every)r   r   rT  s      r   rU  zSeries.gather_every1  s1    l **""//!F/C
 	
r!   c                6    | j                   j                         S )a  Convert to arrow.

        Returns:
            A PyArrow Array containing the data from the Series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeries

            >>> data = [1, 2, 3, 4]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function that converts to arrow:

            >>> def agnostic_to_arrow(s_native: IntoSeries) -> pa.Array:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.to_arrow()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_arrow`:

            >>> agnostic_to_arrow(s_pd)  # doctest:+NORMALIZE_WHITESPACE
            <pyarrow.lib.Int64Array object at ...>
            [
                1,
                2,
                3,
                4
            ]

            >>> agnostic_to_arrow(s_pl)  # doctest:+NORMALIZE_WHITESPACE
            <pyarrow.lib.Int64Array object at ...>
            [
                1,
                2,
                3,
                4
            ]

            >>> agnostic_to_arrow(s_pa)  # doctest:+NORMALIZE_WHITESPACE
            <pyarrow.lib.Int64Array object at ...>
            [
                1,
                2,
                3,
                4
            ]
        )r'   rO   r0   s    r   rO   zSeries.to_arrowk  s    l %%..00r!   c                T    | j                  | j                  j                               S )a  Compute the most occurring value(s).

        Can return multiple values.

        Returns:
            A new Series containing the mode(s) (values that appear most frequently).

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 1, 2, 2, 3]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_mode(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.mode().sort().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_mode`:

            >>> agnostic_mode(s_pd)
            0    1
            1    2
            dtype: int64

            >>> agnostic_mode(s_pl)  # doctest:+NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i64]
            [
               1
               2
            ]

            >>> agnostic_mode(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                2
              ]
            ]
        )rC   r'   moder0   s    r   rX  zSeries.mode  s%    f **4+A+A+F+F+HIIr!   c                T    | j                  | j                  j                               S )a  Returns a boolean Series indicating which values are finite.

        Warning:
            Different backend handle null values differently. `is_finite` will return
            False for NaN and Null's in the Dask and pandas non-nullable backend, while
            for Polars, PyArrow and pandas nullable backends null values are kept as such.

        Returns:
            Expression of `Boolean` data type.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [float("nan"), float("inf"), 2.0, None]

            We define a library agnostic function:

            >>> def agnostic_is_finite(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.is_finite().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_is_finite`:

            >>> agnostic_is_finite(pd.Series(data))
            0    False
            1    False
            2     True
            3    False
            dtype: bool

            >>> agnostic_is_finite(pl.Series(data))  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [bool]
            [
               false
               false
               true
               null
            ]

            >>> agnostic_is_finite(pa.chunked_array([data]))  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                false,
                false,
                true,
                null
              ]
            ]
        )rC   r'   	is_finiter0   s    r   rZ  zSeries.is_finite  s%    r **4+A+A+K+K+MNNr!   c               X    | j                  | j                  j                  |            S )a
  Return the cumulative count of the non-null values in the series.

        Arguments:
            reverse: reverse the operation

        Returns:
            A new Series with the cumulative count of non-null values.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["x", "k", None, "d"]

            We define a library agnostic function:

            >>> def agnostic_cum_count(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.cum_count(reverse=True).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_cum_count`:

            >>> agnostic_cum_count(pd.Series(data))
            0    3
            1    2
            2    1
            3    1
            dtype: int64

            >>> agnostic_cum_count(pl.Series(data))  # doctest:+NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [u32]
            [
                3
                2
                1
                1
            ]

            >>> agnostic_cum_count(pa.chunked_array([data]))  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                3,
                2,
                1,
                1
              ]
            ]

        r   )rC   r'   	cum_countr   s     r   r\  zSeries.cum_count  s/    p **"",,W,=
 	
r!   c               X    | j                  | j                  j                  |            S )a  Return the cumulative min of the non-null values in the series.

        Arguments:
            reverse: reverse the operation

        Returns:
            A new Series with the cumulative min of non-null values.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [3, 1, None, 2]

            We define a library agnostic function:

            >>> def agnostic_cum_min(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.cum_min().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_cum_min`:

            >>> agnostic_cum_min(pd.Series(data))
            0    3.0
            1    1.0
            2    NaN
            3    1.0
            dtype: float64

            >>> agnostic_cum_min(pl.Series(data))  # doctest:+NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [i64]
            [
               3
               1
               null
               1
            ]

            >>> agnostic_cum_min(pa.chunked_array([data]))  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                3,
                1,
                null,
                1
              ]
            ]

        r   )rC   r'   cum_minr   s     r   r^  zSeries.cum_minO  /    p **""**7*;
 	
r!   c               X    | j                  | j                  j                  |            S )a  Return the cumulative max of the non-null values in the series.

        Arguments:
            reverse: reverse the operation

        Returns:
            A new Series with the cumulative max of non-null values.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 3, None, 2]

            We define a library agnostic function:

            >>> def agnostic_cum_max(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.cum_max().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_cum_max`:

            >>> agnostic_cum_max(pd.Series(data))
            0    1.0
            1    3.0
            2    NaN
            3    3.0
            dtype: float64

            >>> agnostic_cum_max(pl.Series(data))  # doctest:+NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [i64]
            [
               1
               3
               null
               3
            ]

            >>> agnostic_cum_max(pa.chunked_array([data]))  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                3,
                null,
                3
              ]
            ]

        r   )rC   r'   cum_maxr   s     r   ra  zSeries.cum_max  r_  r!   c               X    | j                  | j                  j                  |            S )a  Return the cumulative product of the non-null values in the series.

        Arguments:
            reverse: reverse the operation

        Returns:
            A new Series with the cumulative product of non-null values.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1, 3, None, 2]

            We define a library agnostic function:

            >>> def agnostic_cum_prod(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.cum_prod().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_cum_prod`:

            >>> agnostic_cum_prod(pd.Series(data))
            0    1.0
            1    3.0
            2    NaN
            3    6.0
            dtype: float64

            >>> agnostic_cum_prod(pl.Series(data))  # doctest:+NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [i64]
            [
               1
               3
               null
               6
            ]

            >>> agnostic_cum_prod(pa.chunked_array([data]))  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                3,
                null,
                6
              ]
            ]

        r   )rC   r'   cum_prodr   s     r   rc  zSeries.cum_prod  s/    p **""++G+<
 	
r!   )r{   centerc                   t        ||      \  }}t        |       dk(  r| S | j                  | j                  j	                  |||            S )a	  Apply a rolling sum (moving sum) over the values.

        !!! warning
            This functionality is considered **unstable**. It may be changed at any point
            without it being considered a breaking change.

        A window of length `window_size` will traverse the values. The resulting values
        will be aggregated to their sum.

        The window at a given row will include the row itself and the `window_size - 1`
        elements before it.

        Arguments:
            window_size: The length of the window in number of elements. It must be a
                strictly positive integer.
            min_periods: The number of values in the window that should be non-null before
                computing a result. If set to `None` (default), it will be set equal to
                `window_size`. If provided, it must be a strictly positive integer, and
                less than or equal to `window_size`
            center: Set the labels at the center of the window.

        Returns:
            A new series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1.0, 2.0, 3.0, 4.0]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_rolling_sum(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.rolling_sum(window_size=2).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_rolling_sum`:

            >>> agnostic_rolling_sum(s_pd)
            0    NaN
            1    3.0
            2    5.0
            3    7.0
            dtype: float64

            >>> agnostic_rolling_sum(s_pl)  # doctest:+NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [f64]
            [
               null
               3.0
               5.0
               7.0
            ]

            >>> agnostic_rolling_sum(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                null,
                3,
                5,
                7
              ]
            ]
        window_sizer{   r   rg  r{   rd  )r   rn   rC   r'   rolling_sumr   rg  r{   rd  s       r   ri  zSeries.rolling_sum  s`    ` $?#$
 [ t9>K**""..'' / 
 	
r!   c                   t        ||      \  }}t        |       dk(  r| S | j                  | j                  j	                  |||            S )a	  Apply a rolling mean (moving mean) over the values.

        !!! warning
            This functionality is considered **unstable**. It may be changed at any point
            without it being considered a breaking change.

        A window of length `window_size` will traverse the values. The resulting values
        will be aggregated to their mean.

        The window at a given row will include the row itself and the `window_size - 1`
        elements before it.

        Arguments:
            window_size: The length of the window in number of elements. It must be a
                strictly positive integer.
            min_periods: The number of values in the window that should be non-null before
                computing a result. If set to `None` (default), it will be set equal to
                `window_size`. If provided, it must be a strictly positive integer, and
                less than or equal to `window_size`
            center: Set the labels at the center of the window.

        Returns:
            A new series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1.0, 2.0, 3.0, 4.0]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_rolling_mean(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.rolling_mean(window_size=2).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_rolling_mean`:

            >>> agnostic_rolling_mean(s_pd)
            0    NaN
            1    1.5
            2    2.5
            3    3.5
            dtype: float64

            >>> agnostic_rolling_mean(s_pl)  # doctest:+NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [f64]
            [
               null
               1.5
               2.5
               3.5
            ]

            >>> agnostic_rolling_mean(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                null,
                1.5,
                2.5,
                3.5
              ]
            ]
        rf  r   rh  )r   rn   rC   r'   rolling_meanrj  s       r   rl  zSeries.rolling_meanb  s`    ` $?#$
 [ t9>K**""//'' 0 
 	
r!   )r{   rd  r   c                   t        ||      \  }}t        |       dk(  r| S | j                  | j                  j	                  ||||            S )a/
  Apply a rolling variance (moving variance) over the values.

        !!! warning
            This functionality is considered **unstable**. It may be changed at any point
            without it being considered a breaking change.

        A window of length `window_size` will traverse the values. The resulting values
        will be aggregated to their variance.

        The window at a given row will include the row itself and the `window_size - 1`
        elements before it.

        Arguments:
            window_size: The length of the window in number of elements. It must be a
                strictly positive integer.
            min_periods: The number of values in the window that should be non-null before
                computing a result. If set to `None` (default), it will be set equal to
                `window_size`. If provided, it must be a strictly positive integer, and
                less than or equal to `window_size`.
            center: Set the labels at the center of the window.
            ddof: Delta Degrees of Freedom; the divisor for a length N window is N - ddof.

        Returns:
            A new series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1.0, 3.0, 1.0, 4.0]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_rolling_var(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.rolling_var(window_size=2, min_periods=1).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_rolling_var`:

            >>> agnostic_rolling_var(s_pd)
            0    NaN
            1    2.0
            2    2.0
            3    4.5
            dtype: float64

            >>> agnostic_rolling_var(s_pl)  # doctest:+NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [f64]
            [
               null
               2.0
               2.0
               4.5
            ]

            >>> agnostic_rolling_var(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                nan,
                2,
                2,
                4.5
              ]
            ]
        rf  r   rg  r{   rd  r   )r   rn   rC   r'   rolling_varr   rg  r{   rd  r   s        r   ro  zSeries.rolling_var  a    d $?#$
 [ t9>K**""..'[VZ / 
 	
r!   c                   t        ||      \  }}t        |       dk(  r| S | j                  | j                  j	                  ||||            S )a
  Apply a rolling standard deviation (moving standard deviation) over the values.

        !!! warning
            This functionality is considered **unstable**. It may be changed at any point
            without it being considered a breaking change.

        A window of length `window_size` will traverse the values. The resulting values
        will be aggregated to their standard deviation.

        The window at a given row will include the row itself and the `window_size - 1`
        elements before it.

        Arguments:
            window_size: The length of the window in number of elements. It must be a
                strictly positive integer.
            min_periods: The number of values in the window that should be non-null before
                computing a result. If set to `None` (default), it will be set equal to
                `window_size`. If provided, it must be a strictly positive integer, and
                less than or equal to `window_size`.
            center: Set the labels at the center of the window.
            ddof: Delta Degrees of Freedom; the divisor for a length N window is N - ddof.

        Returns:
            A new series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [1.0, 3.0, 1.0, 4.0]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_rolling_std(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.rolling_std(window_size=2, min_periods=1).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_rolling_std`:

            >>> agnostic_rolling_std(s_pd)
            0         NaN
            1    1.414214
            2    1.414214
            3    2.121320
            dtype: float64

            >>> agnostic_rolling_std(s_pl)  # doctest:+NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [f64]
            [
               null
               1.414214
               1.414214
               2.12132
            ]

            >>> agnostic_rolling_std(s_pa)  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                nan,
                1.4142135623730951,
                1.4142135623730951,
                2.1213203435596424
              ]
            ]
        rf  r   rn  )r   rn   rC   r'   rolling_stdrp  s        r   rs  zSeries.rolling_std   rq  r!   c              #  T   K   | j                   j                         E d {    y 7 wr7   )r'   __iter__r0   s    r   ru  zSeries.__iter__  s     ))22444s   (&(c                8    | j                   j                  |      S r7   )r'   __contains__r   s     r   rw  zSeries.__contains__  s    %%22599r!   c                   h d}||vrd| d}t        |      | j                  | j                  j                  ||            S )a
  Assign ranks to data, dealing with ties appropriately.

        Notes:
            The resulting dtype may differ between backends.

        Arguments:
            method: The method used to assign ranks to tied elements.
                The following methods are available (default is 'average'):

                - 'average' : The average of the ranks that would have been assigned to
                  all the tied values is assigned to each value.
                - 'min' : The minimum of the ranks that would have been assigned to all
                    the tied values is assigned to each value. (This is also referred to
                    as "competition" ranking.)
                - 'max' : The maximum of the ranks that would have been assigned to all
                    the tied values is assigned to each value.
                - 'dense' : Like 'min', but the rank of the next highest element is
                   assigned the rank immediately after those assigned to the tied
                   elements.
                - 'ordinal' : All values are given a distinct rank, corresponding to the
                    order that the values occur in the Series.

            descending: Rank in descending order.

        Returns:
            A new series with rank data as values.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT
            >>>
            >>> data = [3, 6, 1, 1, 6]

            We define a dataframe-agnostic function that computes the dense rank for
            the data:

            >>> def agnostic_dense_rank(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.rank(method="dense").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_dense_rank`:

            >>> agnostic_dense_rank(pd.Series(data))
            0    2.0
            1    3.0
            2    1.0
            3    1.0
            4    3.0
            dtype: float64

            >>> agnostic_dense_rank(pl.Series(data))  # doctest:+NORMALIZE_WHITESPACE
            shape: (5,)
            Series: '' [u32]
            [
               2
               3
               1
               1
               3
            ]

            >>> agnostic_dense_rank(pa.chunked_array([data]))  # doctest:+ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2,
                3,
                1,
                1,
                3
              ]
            ]
        >   r   r   denseaverageordinalzTRanking method must be one of {'average', 'min', 'max', 'dense', 'ordinal'}. Found '')methodr   )r   rC   r'   rank)r   r}  r   supported_rank_methodsr,   s        r   r~  zSeries.rank  sc    f "O// $  S/!**""''v*'M
 	
r!   c                    t        |       S r7   )SeriesStringNamespacer0   s    r   strz
Series.str  s    $T**r!   c                    t        |       S r7   )SeriesDateTimeNamespacer0   s    r   dtz	Series.dt  s    &t,,r!   c                    t        |       S r7   )SeriesCatNamespacer0   s    r   catz
Series.cat  s    !$''r!   c                    t        |       S r7   )SeriesListNamespacer0   s    r   r   zSeries.list  s    "4((r!   )returnztype[DataFrame[Any]])r   r   r*   r   r+   z&Literal['full', 'lazy', 'interchange']r  None)r  r   )NN)r   r   r3   r   r4   zbool | Noner  
np.ndarray)r   r   r:   rA   r  r   )r   r   r:   zslice | Sequence[int]r  r   )r   r   r:   zint | slice | Sequence[int]r  
Any | Self)r   r   r  r   r7   )rH   zobject | Noner  object)r  r   )rY   zint | Sequence[int]rZ   r   r  r   )r  z
tuple[int])r`   r   r  r   )r*   r   r  r   )rf   zCallable[[Any], Self]rg   r   rh   r   r  r   )r  r  )r  rA   )r   r   r  r   )r   r   rv   float | Nonerw   r  rx   r  ry   r  rz   boolr{   rA   r|   r  r  r   )r   r   r3   zDType | type[DType]r  r   )r  DataFrame[Any])r  z	list[Any])r  r   )r   r   r  r   )r   rA   r  r   )r   Self | Any | Noner   r  r  r   )r   r   r  r   )r  r   )r   r   r   r  r  r   )r   r  r  r   )r   rA   r  r   )r   r   r   
int | Noner   r  r   r  r   r  r  r   )rs   r  r  r   )
r   r   r   z!Sequence[Any] | Mapping[Any, Any]r   zSequence[Any] | Noner   zDType | type[DType] | Noner  r   )r   r  r   r  r  r   )NNN)r   z
Any | Noner   z%Literal['forward', 'backward'] | Noner   r  r  r   )both)r   r  r   r  r   r  r  r   )r  r  )r  z	pd.Series)r   r  r  r   )r   r   r  r   )r   r   r  r  )r   r   r  rA   )r   r   r   r  r  r  )r   r   r   r  r8  r  rs   
str | Noner9  r  r  r  )r=  floatr>  z;Literal['nearest', 'higher', 'lower', 'midpoint', 'linear']r  r   )r   r   rA  r   r   r   r  r   )r   r   rC  r  r  r   )
   )r   r   r   rA   r  r   )r   )r   r   rL  rA   r  r   )r   r   rO  r  rP  r  r  r  )r   r   r   rA   rT  rA   r  r   )r   r   r  zpa.Array)
r   r   rg  rA   r{   r  rd  r  r  r   )r   r   rg  rA   r{   r  rd  r  r   rA   r  r   )r   r   r  zIterator[Any])r   r   r   r   r  r  )rz  )r   r   r}  z4Literal['average', 'min', 'max', 'dense', 'ordinal']r   r  r  r   )r   r   r  zSeriesStringNamespace[Self])r   r   r  zSeriesDateTimeNamespace[Self])r   r   r  zSeriesCatNamespace[Self])r   r   r  zSeriesListNamespace[Self])z__name__
__module____qualname____doc__propertyr    r-   r1   r5   r   r;   rE   rG   rU   rW   r\   rX   rC   ri   rk   ro   rn   r3   rs   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r
  r  r  r  r  r  r  r  r  r  r  r!  r#  r%  r'  r)  r+  r-  r/  r1  r3  r6  r;  r=  r@  rD  rF  rI  rK  rR  rU  rO   rX  rZ  r\  r^  ra  rc  ri  rl  ro  rs  ru  rw  r~  r  r  r  r   r8   r!   r   r   r   "   s(   0  
&&& 6	&
 
& 6 6<H 5 5H HLH\=H245lP
d $, $,L
4/lM+&+P $, $,L  +  +J !!"&""`
`
 `
 	`

  `
 `
 `
 `
 `
 
`
D8Ot5
n*0X$-L'/R(-T$.L',R$,L$,L$,L!0F!0F$,L "# (5T "# %5P W[S
,S
BSS
	S
j9
v1Nf<P|4Il 05 9
v 05 ;
z=J~ALJ N
 "&!&N
N
N
 	N

 N
 N
 
N
`JTXL%b %)T

 48T
T
.T
 "T

 1T
 
T
l */5 ]
~9Mv3Ln !:> 	m
m
 8m
 	m

 
m
` OUK
%K
4>K
HKK
	K
Z$1L%1N-2^














































P6
r7Sr%1N6Op*3X:Wx:Vx 5: .Gf L
L
 L
 	L

 L
 L
 
L
\4
4
 S4
 
	4
lT
l'8R7Kr7Kr?SD ),`
`
"%`
9=`
	`
D8
t61p3Jj9Ov 27 :
x 05 :
x 05 :
x 16 :
@ #']
]
]
  	]

 ]
 
]
F #']
]
]
  	]

 ]
 
]
F #']
]
]
  	]

 ]
 ]
 
]
F #']
]
]
  	]

 ]
 ]
 
]
~5:
 HQ]
 !	]
]
D]
 	]

 
]
~ + + - - ( ( ) )r!   r   SeriesT)boundc                      e Zd ZddZddZy)r  c                    || _         y r7   _narwhals_seriesrd   s     r   r-   zSeriesCatNamespace.__init__  
     &r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a_  Get unique categories from column.

        Returns:
            A new Series containing the unique categories.

        Examples:
            Let's create some series:

            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["apple", "mango", "mango"]
            >>> s_pd = pd.Series(data, dtype="category")
            >>> s_pl = pl.Series(data, dtype=pl.Categorical)
            >>> s_pa = pa.chunked_array([data]).dictionary_encode()

            We define a dataframe-agnostic function to get unique categories
            from column 'fruits':

            >>> def agnostic_get_categories(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.cat.get_categories().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_get_categories`:

            >>> agnostic_get_categories(s_pd)
            0    apple
            1    mango
            dtype: object

            >>> agnostic_get_categories(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [str]
            [
               "apple"
               "mango"
            ]

            >>> agnostic_get_categories(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "apple",
                "mango"
              ]
            ]
        )r  rC   r'   r  get_categoriesr0   s    r   r  z!SeriesCatNamespace.get_categories  s<    h $$;;!!3377FFH
 	
r!   Nr   r   r*   r  r  r  r   r   r  r  )r  r  r  r-   r  r8   r!   r   r  r    s    '6
r!   r  c                      e Zd ZddZddZddd	 	 	 	 	 	 	 	 	 	 	 ddZdd	 	 	 	 	 	 	 	 	 ddZddd
ZddZddZ	ddddZ
dddZdddZdddZd dZd dZdd!dZy	)"r  c                    || _         y r7   r  rd   s     r   r-   zSeriesStringNamespace.__init__6  r  r!   c                    | j                   j                  | j                   j                  j                  j	                               S )us  Return the length of each string as the number of characters.

        Returns:
            A new Series containing the length of each string in characters.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["foo", "Café", "345", "東京", None]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_len_chars(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.len_chars().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_len_chars`:

            >>> agnostic_len_chars(s_pd)
            0    3.0
            1    4.0
            2    3.0
            3    2.0
            4    NaN
            dtype: float64

            >>> agnostic_len_chars(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (5,)
            Series: '' [u32]
            [
               3
               4
               3
               2
               null
            ]

            >>> agnostic_len_chars(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                3,
                4,
                3,
                2,
                null
              ]
            ]
        )r  rC   r'   r  	len_charsr0   s    r   r  zSeriesStringNamespace.len_chars9  s<    t $$;;!!3377AAC
 	
r!   Frt   literalr   c                   | j                   j                  | j                   j                  j                  j	                  ||||            S )a  Replace first matching regex/literal substring with a new string value.

        Arguments:
            pattern: A valid regular expression pattern.
            value: String that will replace the matched substring.
            literal: Treat `pattern` as a literal string.
            n: Number of matches to replace.

        Returns:
            A new Series with the regex/literal pattern replaced with the specified value.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["123abc", "abc abc123"]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_replace(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     s = s.str.replace("abc", "")
            ...     return s.to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_replace`:

            >>> agnostic_replace(s_pd)
            0        123
            1     abc123
            dtype: object

            >>> agnostic_replace(s_pl)  # doctest:+NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [str]
            [
                "123"
                " abc123"
            ]

            >>> agnostic_replace(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "123",
                " abc123"
              ]
            ]
        r  )r  rC   r'   r  replace)r   patternr   r  r   s        r   r  zSeriesStringNamespace.replacew  sM    t $$;;!!3377??1 @ 
 	
r!   r  c                   | j                   j                  | j                   j                  j                  j	                  |||            S )a  Replace all matching regex/literal substring with a new string value.

        Arguments:
            pattern: A valid regular expression pattern.
            value: String that will replace the matched substring.
            literal: Treat `pattern` as a literal string.

        Returns:
            A new Series with all occurrences of pattern replaced with the specified value.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["123abc", "abc abc123"]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_replace_all(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     s = s.str.replace_all("abc", "")
            ...     return s.to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_replace_all`:

            >>> agnostic_replace_all(s_pd)
            0     123
            1     123
            dtype: object

            >>> agnostic_replace_all(s_pl)  # doctest:+NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [str]
            [
                "123"
                " 123"
            ]

            >>> agnostic_replace_all(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "123",
                " 123"
              ]
            ]
        r  )r  rC   r'   r  replace_all)r   r  r   r  s       r   r  z!SeriesStringNamespace.replace_all  sK    r $$;;!!3377CC D 
 	
r!   Nc                    | j                   j                  | j                   j                  j                  j	                  |            S )a  Remove leading and trailing characters.

        Arguments:
            characters: The set of characters to be removed. All combinations of this set of characters will be stripped from the start and end of the string. If set to None (default), all leading and trailing whitespace is removed instead.

        Returns:
            A new Series with leading and trailing characters removed.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["apple", "\nmango"]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_strip_chars(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     s = s.str.strip_chars()
            ...     return s.to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_strip_chars`:

            >>> agnostic_strip_chars(s_pd)
            0    apple
            1    mango
            dtype: object

            >>> agnostic_strip_chars(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [str]
            [
                "apple"
                "mango"
            ]

            >>> agnostic_strip_chars(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "apple",
                "mango"
              ]
            ]
        )r  rC   r'   r  strip_chars)r   
characterss     r   r  z!SeriesStringNamespace.strip_chars  s>    j $$;;!!3377CCJO
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                  |            S )aS  Check if string values start with a substring.

        Arguments:
            prefix: prefix substring

        Returns:
            A new Series with boolean values indicating if each string starts with the prefix.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["apple", "mango", None]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_starts_with(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.starts_with("app").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_starts_with`:

            >>> agnostic_starts_with(s_pd)
            0     True
            1    False
            2     None
            dtype: object

            >>> agnostic_starts_with(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [bool]
            [
               true
               false
               null
            ]

            >>> agnostic_starts_with(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                true,
                false,
                null
              ]
            ]
        )r  rC   r'   r  starts_with)r   prefixs     r   r  z!SeriesStringNamespace.starts_with/  s>    n $$;;!!3377CCFK
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                  |            S )aC  Check if string values end with a substring.

        Arguments:
            suffix: suffix substring

        Returns:
            A new Series with boolean values indicating if each string ends with the suffix.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["apple", "mango", None]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_ends_with(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.ends_with("ngo").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_ends_with`:

            >>> agnostic_ends_with(s_pd)
            0    False
            1     True
            2     None
            dtype: object

            >>> agnostic_ends_with(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [bool]
            [
               false
               true
               null
            ]

            >>> agnostic_ends_with(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                false,
                true,
                null
              ]
            ]
        )r  rC   r'   r  	ends_with)r   suffixs     r   r  zSeriesStringNamespace.ends_withj  s>    n $$;;!!3377AA&I
 	
r!   c                   | j                   j                  | j                   j                  j                  j	                  ||            S )a  Check if string contains a substring that matches a pattern.

        Arguments:
            pattern: A Character sequence or valid regular expression pattern.
            literal: If True, treats the pattern as a literal string.
                     If False, assumes the pattern is a regular expression.

        Returns:
            A new Series with boolean values indicating if each string contains the pattern.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["cat", "dog", "rabbit and parrot", "dove", None]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_contains(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.contains("parrot|dove").to_native()

            We can then pass any supported library such as pandas, Polars, or PyArrow to `agnostic_contains`:

            >>> agnostic_contains(s_pd)
            0    False
            1    False
            2     True
            3     True
            4     None
            dtype: object

            >>> agnostic_contains(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (5,)
            Series: '' [bool]
            [
               false
               false
               true
               true
               null
            ]

            >>> agnostic_contains(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                false,
                false,
                true,
                true,
                null
              ]
            ]
        r  )r  rC   r'   r  contains)r   r  r  s      r   r  zSeriesStringNamespace.contains  sD    | $$;;!!3377@@RY@Z
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                  ||            S )a
  Create subslices of the string values of a Series.

        Arguments:
            offset: Start index. Negative indexing is supported.
            length: Length of the slice. If set to `None` (default), the slice is taken to the
                end of the string.

        Returns:
            A new Series containing subslices of each string.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["pear", None, "papaya", "dragonfruit"]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_slice(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.slice(4, length=3).to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_slice`:

            >>> agnostic_slice(s_pd)  # doctest: +NORMALIZE_WHITESPACE
            0
            1    None
            2      ya
            3     onf
            dtype: object

            >>> agnostic_slice(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [str]
            [
               ""
               null
               "ya"
               "onf"
            ]

            >>> agnostic_slice(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "",
                null,
                "ya",
                "onf"
              ]
            ]

            Using negative indexes:

            >>> def agnostic_slice(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.slice(-3).to_native()

            >>> agnostic_slice(s_pd)  # doctest: +NORMALIZE_WHITESPACE
            0     ear
            1    None
            2     aya
            3     uit
            dtype: object

            >>> agnostic_slice(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [str]
            [
                "ear"
                null
                "aya"
                "uit"
            ]

            >>> agnostic_slice(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "ear",
                null,
                "aya",
                "uit"
              ]
            ]
        rT  lengthr  rC   r'   r  slice)r   rT  r  s      r   r  zSeriesStringNamespace.slice  sH    | $$;;!!3377==f > 
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                  d|            S )a  Take the first n elements of each string.

        Arguments:
            n: Number of elements to take. Negative indexing is supported (see note (1.))

        Returns:
            A new Series containing the first n characters of each string.

        Notes:
            1. When the `n` input is negative, `head` returns characters up to the n-th from the end of the string.
                For example, if `n = -3`, then all characters except the last three are returned.
            2. If the length of the string has fewer than `n` characters, the full string is returned.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["Atatata", "taata", "taatatata", "zukkyun"]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_head(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.head().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_head`:

            >>> agnostic_head(s_pd)
            0    Atata
            1    taata
            2    taata
            3    zukky
            dtype: object

            >>> agnostic_head(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [str]
            [
               "Atata"
               "taata"
               "taata"
               "zukky"
            ]

            >>> agnostic_head(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "Atata",
                "taata",
                "taata",
                "zukky"
              ]
            ]
        r   r  r  r   s     r   rF  zSeriesStringNamespace.headK  sC    ~ $$;;!!3377==Qq=Q
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                  | d            S )a  Take the last n elements of each string.

        Arguments:
            n: Number of elements to take. Negative indexing is supported (see note (1.))

        Returns:
            A new Series containing the last n characters of each string.

        Notes:
            1. When the `n` input is negative, `tail` returns characters starting from the n-th from the beginning of
                the string. For example, if `n = -3`, then all characters except the first three are returned.
            2. If the length of the string has fewer than `n` characters, the full string is returned.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["Atatata", "taata", "taatatata", "zukkyun"]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_tail(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.tail().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_tail`:

            >>> agnostic_tail(s_pd)
            0    atata
            1    taata
            2    atata
            3    kkyun
            dtype: object

            >>> agnostic_tail(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [str]
            [
               "atata"
               "taata"
               "atata"
               "kkyun"
            ]

            >>> agnostic_tail(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "atata",
                "taata",
                "atata",
                "kkyun"
              ]
            ]
        Nr  r  r   s     r   rI  zSeriesStringNamespace.tail  sF    ~ $$;;!!3377==aRPT=U
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )u  Transform string to uppercase variant.

        Returns:
            A new Series with values converted to uppercase.

        Notes:
            The PyArrow backend will convert 'ß' to 'ẞ' instead of 'SS'.
            For more info see: https://github.com/apache/arrow/issues/34599
            There may be other unicode-edge-case-related variations across implementations.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["apple", "mango", None]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_to_uppercase(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.to_uppercase().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_uppercase`:

            >>> agnostic_to_uppercase(s_pd)
            0    APPLE
            1    MANGO
            2     None
            dtype: object

            >>> agnostic_to_uppercase(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [str]
            [
               "APPLE"
               "MANGO"
               null
            ]

            >>> agnostic_to_uppercase(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "APPLE",
                "MANGO",
                null
              ]
            ]
        )r  rC   r'   r  to_uppercaser0   s    r   r  z"SeriesStringNamespace.to_uppercase  s<    r $$;;!!3377DDF
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Transform string to lowercase variant.

        Returns:
            A new Series with values converted to lowercase.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["APPLE", "MANGO", None]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_to_lowercase(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.to_lowercase().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_lowercase`:

            >>> agnostic_to_lowercase(s_pd)
            0    apple
            1    mango
            2     None
            dtype: object

            >>> agnostic_to_lowercase(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [str]
            [
               "apple"
               "mango"
               null
            ]

            >>> agnostic_to_lowercase(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "apple",
                "mango",
                null
              ]
            ]
        )r  rC   r'   r  to_lowercaser0   s    r   r  z"SeriesStringNamespace.to_lowercase  s<    h $$;;!!3377DDF
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                  |            S )u  Parse Series with strings to a Series with Datetime dtype.

        Notes:
            pandas defaults to nanosecond time unit, Polars to microsecond.
            Prior to pandas 2.0, nanoseconds were the only time unit supported
            in pandas, with no ability to set any other one. The ability to
            set the time unit in pandas, if the version permits, will arrive.

        Warning:
            As different backends auto-infer format in different ways, if `format=None`
            there is no guarantee that the result will be equal.

        Arguments:
            format: Format to use for conversion. If set to None (default), the format is
                inferred from the data.

        Returns:
            A new Series with datetime dtype.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["2020-01-01", "2020-01-02"]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_to_datetime(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.str.to_datetime(format="%Y-%m-%d").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_datetime`:

            >>> agnostic_to_datetime(s_pd)
            0   2020-01-01
            1   2020-01-02
            dtype: datetime64[ns]

            >>> agnostic_to_datetime(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [datetime[μs]]
            [
               2020-01-01 00:00:00
               2020-01-02 00:00:00
            ]

            >>> agnostic_to_datetime(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at 0x...>
            [
              [
                2020-01-01 00:00:00.000000,
                2020-01-02 00:00:00.000000
              ]
            ]
        )format)r  rC   r'   r  to_datetimer   r  s     r   r  z!SeriesStringNamespace.to_datetimeF  sA    ~ $$;;!!3377CC6CR
 	
r!   r  r  )r   r   r  r  r   r  r  r  r   rA   r  r  )
r   r   r  r  r   r  r  r  r  r  r7   )r   r   r  r  r  r  )r   r   r  r  r  r  )r   r   r  r  r  r  )r   r   r  r  r  r  r  r  )r   r   rT  rA   r  r  r  r  )   )r   r   r   rA   r  r  )r  r  )r   r   r  r  r  r  )r  r  r  r-   r  r  r  r  r  r  r  r  rF  rI  r  r  r  r8   r!   r   r  r  5  s    '<
~ BGQR>
>
 >
),>
:>>
KN>
	>
B BG=
=
 =
),=
:>=
	=
~7
r9
v9
v ?D @
Db
HA
FA
F;
z6
pA
r!   r  c                      e Zd ZddZddZddZddZddZddZddZ	ddZ
dd	Zdd
ZddZddZddZddZddZddZddZddZddZddZddZdddZy)r  c                    || _         y r7   r  rd   s     r   r-   z SeriesDateTimeNamespace.__init__  r  r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Get the date in a datetime series.

        Returns:
            A new Series with the date portion of the datetime values.

        Raises:
            NotImplementedError: If pandas default backend is being used.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> dates = [datetime(2012, 1, 7, 10, 20), datetime(2023, 3, 10, 11, 32)]
            >>> s_pd = pd.Series(dates).convert_dtypes(dtype_backend="pyarrow")
            >>> s_pl = pl.Series(dates)
            >>> s_pa = pa.chunked_array([dates])

            We define a library agnostic function:

            >>> def agnostic_date(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.date().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_date`:

            >>> agnostic_date(s_pd)
            0    2012-01-07
            1    2023-03-10
            dtype: date32[day][pyarrow]

            >>> agnostic_date(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [date]
            [
               2012-01-07
               2023-03-10
            ]

            >>> agnostic_date(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2012-01-07,
                2023-03-10
              ]
            ]
        )r  rC   r'   r  dater0   s    r   r  zSeriesDateTimeNamespace.date  s<    j $$;;!!3366;;=
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Get the year in a datetime series.

        Returns:
            A new Series containing the year component of each datetime value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> dates = [datetime(2012, 1, 7), datetime(2023, 3, 10)]
            >>> s_pd = pd.Series(dates)
            >>> s_pl = pl.Series(dates)
            >>> s_pa = pa.chunked_array([dates])

            We define a library agnostic function:

            >>> def agnostic_year(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.year().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_year`:

            >>> agnostic_year(s_pd)
            0    2012
            1    2023
            dtype: int...

            >>> agnostic_year(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i32]
            [
               2012
               2023
            ]

            >>> agnostic_year(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2012,
                2023
              ]
            ]
        )r  rC   r'   r  yearr0   s    r   r  zSeriesDateTimeNamespace.year  <    d $$;;!!3366;;=
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Gets the month in a datetime series.

        Returns:
            A new Series containing the month component of each datetime value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> dates = [datetime(2023, 2, 1), datetime(2023, 8, 3)]
            >>> s_pd = pd.Series(dates)
            >>> s_pl = pl.Series(dates)
            >>> s_pa = pa.chunked_array([dates])

            We define a library agnostic function:

            >>> def agnostic_month(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.month().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_month`:

            >>> agnostic_month(s_pd)
            0    2
            1    8
            dtype: int...
            >>> agnostic_month(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i8]
            [
               2
               8
            ]

            >>> agnostic_month(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2,
                8
              ]
            ]
        )r  rC   r'   r  monthr0   s    r   r  zSeriesDateTimeNamespace.month  s<    b $$;;!!3366<<>
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Extracts the day in a datetime series.

        Returns:
            A new Series containing the day component of each datetime value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> dates = [datetime(2022, 1, 1), datetime(2022, 1, 5)]
            >>> s_pd = pd.Series(dates)
            >>> s_pl = pl.Series(dates)
            >>> s_pa = pa.chunked_array([dates])

            We define a library agnostic function:

            >>> def agnostic_day(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.day().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_day`:

            >>> agnostic_day(s_pd)
            0    1
            1    5
            dtype: int...

            >>> agnostic_day(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i8]
            [
               1
               5
            ]

            >>> agnostic_day(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                5
              ]
            ]
        )r  rC   r'   r  dayr0   s    r   r  zSeriesDateTimeNamespace.day2  s<    d $$;;!!3366::<
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Extracts the hour in a datetime series.

        Returns:
            A new Series containing the hour component of each datetime value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> dates = [datetime(2022, 1, 1, 5, 3), datetime(2022, 1, 5, 9, 12)]
            >>> s_pd = pd.Series(dates)
            >>> s_pl = pl.Series(dates)
            >>> s_pa = pa.chunked_array([dates])

            We define a library agnostic function:

            >>> def agnostic_hour(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.hour().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_hour`:

            >>> agnostic_hour(s_pd)
            0    5
            1    9
            dtype: int...

            >>> agnostic_hour(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i8]
            [
               5
               9
            ]

            >>> agnostic_hour(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                5,
                9
              ]
            ]
        )r  rC   r'   r  hourr0   s    r   r  zSeriesDateTimeNamespace.hourh  r  r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Extracts the minute in a datetime series.

        Returns:
            A new Series containing the minute component of each datetime value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> dates = [datetime(2022, 1, 1, 5, 3), datetime(2022, 1, 5, 9, 12)]
            >>> s_pd = pd.Series(dates)
            >>> s_pl = pl.Series(dates)
            >>> s_pa = pa.chunked_array([dates])

            We define a library agnostic function:

            >>> def agnostic_minute(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.minute().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_minute`:

            >>> agnostic_minute(s_pd)
            0     3
            1    12
            dtype: int...

            >>> agnostic_minute(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i8]
            [
               3
               12
            ]

            >>> agnostic_minute(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                3,
                12
              ]
            ]
        )r  rC   r'   r  minuter0   s    r   r  zSeriesDateTimeNamespace.minute  <    d $$;;!!3366==?
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Extracts the seconds in a datetime series.

        Returns:
            A new Series containing the second component of each datetime value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> dates = [datetime(2022, 1, 1, 5, 3, 10), datetime(2022, 1, 5, 9, 12, 4)]
            >>> s_pd = pd.Series(dates)
            >>> s_pl = pl.Series(dates)
            >>> s_pa = pa.chunked_array([dates])

            We define a library agnostic function:

            >>> def agnostic_second(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.second().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_second`:

            >>> agnostic_second(s_pd)
            0    10
            1     4
            dtype: int...

            >>> agnostic_second(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i8]
            [
               10
                4
            ]

            >>> agnostic_second(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                10,
                4
              ]
            ]
        )r  rC   r'   r  secondr0   s    r   r  zSeriesDateTimeNamespace.second  r  r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Extracts the milliseconds in a datetime series.

        Returns:
            A new Series containing the millisecond component of each datetime value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> dates = [
            ...     datetime(2023, 5, 21, 12, 55, 10, 400000),
            ...     datetime(2023, 5, 21, 12, 55, 10, 600000),
            ...     datetime(2023, 5, 21, 12, 55, 10, 800000),
            ...     datetime(2023, 5, 21, 12, 55, 11, 0),
            ...     datetime(2023, 5, 21, 12, 55, 11, 200000),
            ... ]
            >>> s_pd = pd.Series(dates)
            >>> s_pl = pl.Series(dates)
            >>> s_pa = pa.chunked_array([dates])

            We define a library agnostic function:

            >>> def agnostic_millisecond(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.millisecond().alias("datetime").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_millisecond`:

            >>> agnostic_millisecond(s_pd)
            0    400
            1    600
            2    800
            3      0
            4    200
            Name: datetime, dtype: int...

            >>> agnostic_millisecond(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (5,)
            Series: 'datetime' [i32]
            [
                400
                600
                800
                0
                200
            ]

            >>> agnostic_millisecond(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                400,
                600,
                800,
                0,
                200
              ]
            ]
        )r  rC   r'   r  millisecondr0   s    r   r  z#SeriesDateTimeNamespace.millisecond
  <    B $$;;!!3366BBD
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a%  Extracts the microseconds in a datetime series.

        Returns:
            A new Series containing the microsecond component of each datetime value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> dates = [
            ...     datetime(2023, 5, 21, 12, 55, 10, 400000),
            ...     datetime(2023, 5, 21, 12, 55, 10, 600000),
            ...     datetime(2023, 5, 21, 12, 55, 10, 800000),
            ...     datetime(2023, 5, 21, 12, 55, 11, 0),
            ...     datetime(2023, 5, 21, 12, 55, 11, 200000),
            ... ]
            >>> s_pd = pd.Series(dates)
            >>> s_pl = pl.Series(dates)
            >>> s_pa = pa.chunked_array([dates])

            We define a library agnostic function:

            >>> def agnostic_microsecond(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.microsecond().alias("datetime").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_microsecond`:

            >>> agnostic_microsecond(s_pd)
            0    400000
            1    600000
            2    800000
            3         0
            4    200000
            Name: datetime, dtype: int...

            >>> agnostic_microsecond(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (5,)
            Series: 'datetime' [i32]
            [
               400000
               600000
               800000
               0
               200000
            ]

            >>> agnostic_microsecond(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                400000,
                600000,
                800000,
                0,
                200000
              ]
            ]
        )r  rC   r'   r  microsecondr0   s    r   r  z#SeriesDateTimeNamespace.microsecondO  r  r!   c                    | j                   j                  | j                   j                  j                  j	                               S )aw  Extract the nanoseconds in a date series.

        Returns:
            A new Series containing the nanosecond component of each datetime value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> dates = [
            ...     datetime(2022, 1, 1, 5, 3, 10, 500000),
            ...     datetime(2022, 1, 5, 9, 12, 4, 60000),
            ... ]
            >>> s_pd = pd.Series(dates)
            >>> s_pl = pl.Series(dates)
            >>> s_pa = pa.chunked_array([dates])

            We define a library agnostic function:

            >>> def agnostic_nanosecond(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.nanosecond().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_nanosecond`:

            >>> agnostic_nanosecond(s_pd)
            0    500000000
            1     60000000
            dtype: int...

            >>> agnostic_nanosecond(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i32]
            [
               500000000
               60000000
            ]

            >>> agnostic_nanosecond(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                500000000,
                60000000
              ]
            ]
        )r  rC   r'   r  
nanosecondr0   s    r   r  z"SeriesDateTimeNamespace.nanosecond  s<    j $$;;!!3366AAC
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Get ordinal day.

        Returns:
            A new Series containing the ordinal day (day of year) for each datetime value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [datetime(2020, 1, 1), datetime(2020, 8, 3)]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_ordinal_day(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.ordinal_day().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_ordinal_day`:

            >>> agnostic_ordinal_day(s_pd)
            0      1
            1    216
            dtype: int32

            >>> agnostic_ordinal_day(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i16]
            [
               1
               216
            ]


            >>> agnostic_ordinal_day(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                1,
                216
              ]
            ]
        )r  rC   r'   r  ordinal_dayr0   s    r   r  z#SeriesDateTimeNamespace.ordinal_day  s<    f $$;;!!3366BBD
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Extract the week day in a datetime series.

        Returns:
            A new Series containing the week day for each datetime value.
            Returns the ISO weekday number where monday = 1 and sunday = 7


        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT
            >>> data = [datetime(2020, 1, 1), datetime(2020, 8, 3)]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_weekday(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.weekday().to_native()

            We can then pass either pandas, Polars, PyArrow, and other supported libraries to `agnostic_weekday`:

            >>> agnostic_weekday(s_pd)
            0    3
            1    1
            dtype: int32
            >>> agnostic_weekday(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i8]
            [
               3
               1
            ]
            >>> agnostic_weekday(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                3,
                1
              ]
            ]
        )r  rC   r'   r  weekdayr0   s    r   r  zSeriesDateTimeNamespace.weekday  s<    ` $$;;!!3366>>@
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Get total minutes.

        Notes:
            The function outputs the total minutes in the int dtype by default,
            however, pandas may change the dtype to float when there are missing values,
            consider using `fill_null()` in this case.

        Returns:
            A new Series containing the total number of minutes for each timedelta value.

        Examples:
            >>> from datetime import timedelta
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [timedelta(minutes=10), timedelta(minutes=20, seconds=40)]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_total_minutes(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.total_minutes().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_total_minutes`:

            >>> agnostic_total_minutes(s_pd)
            0    10
            1    20
            dtype: int...

            >>> agnostic_total_minutes(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i64]
            [
                    10
                    20
            ]

            >>> agnostic_total_minutes(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                10,
                20
              ]
            ]
        )r  rC   r'   r  total_minutesr0   s    r   r  z%SeriesDateTimeNamespace.total_minutes8  <    n $$;;!!3366DDF
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Get total seconds.

        Notes:
            The function outputs the total seconds in the int dtype by default,
            however, pandas may change the dtype to float when there are missing values,
            consider using `fill_null()` in this case.

        Returns:
            A new Series containing the total number of seconds for each timedelta value.

        Examples:
            >>> from datetime import timedelta
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [timedelta(seconds=10), timedelta(seconds=20, milliseconds=40)]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_total_seconds(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.total_seconds().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_total_seconds`:

            >>> agnostic_total_seconds(s_pd)
            0    10
            1    20
            dtype: int...

            >>> agnostic_total_seconds(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i64]
            [
                    10
                    20
            ]

            >>> agnostic_total_seconds(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                10,
                20
              ]
            ]
        )r  rC   r'   r  total_secondsr0   s    r   r  z%SeriesDateTimeNamespace.total_secondss  r  r!   c                    | j                   j                  | j                   j                  j                  j	                               S )am  Get total milliseconds.

        Notes:
            The function outputs the total milliseconds in the int dtype by default,
            however, pandas may change the dtype to float when there are missing values,
            consider using `fill_null()` in this case.

        Returns:
            A new Series containing the total number of milliseconds for each timedelta value.

        Examples:
            >>> from datetime import timedelta
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [
            ...     timedelta(milliseconds=10),
            ...     timedelta(milliseconds=20, microseconds=40),
            ... ]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_total_milliseconds(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.total_milliseconds().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_total_milliseconds`:

            >>> agnostic_total_milliseconds(s_pd)
            0    10
            1    20
            dtype: int...

            >>> agnostic_total_milliseconds(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i64]
            [
                    10
                    20
            ]

            >>> agnostic_total_milliseconds(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                10,
                20
              ]
            ]
        )r  rC   r'   r  total_millisecondsr0   s    r   r  z*SeriesDateTimeNamespace.total_milliseconds  <    t $$;;!!3366IIK
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                               S )am  Get total microseconds.

        Returns:
            A new Series containing the total number of microseconds for each timedelta value.

        Notes:
            The function outputs the total microseconds in the int dtype by default,
            however, pandas may change the dtype to float when there are missing values,
            consider using `fill_null()` in this case.

        Examples:
            >>> from datetime import timedelta
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [
            ...     timedelta(microseconds=10),
            ...     timedelta(milliseconds=1, microseconds=200),
            ... ]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a library agnostic function:

            >>> def agnostic_total_microseconds(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.total_microseconds().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_total_microseconds`:

            >>> agnostic_total_microseconds(s_pd)
            0      10
            1    1200
            dtype: int...

            >>> agnostic_total_microseconds(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i64]
            [
                10
                1200
            ]

            >>> agnostic_total_microseconds(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                10,
                1200
              ]
            ]
        )r  rC   r'   r  total_microsecondsr0   s    r   r  z*SeriesDateTimeNamespace.total_microseconds  r  r!   c                    | j                   j                  | j                   j                  j                  j	                               S )aL  Get total nanoseconds.

        Notes:
            The function outputs the total nanoseconds in the int dtype by default,
            however, pandas may change the dtype to float when there are missing values,
            consider using `fill_null()` in this case.

        Returns:
            A new Series containing the total number of nanoseconds for each timedelta value.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = ["2024-01-01 00:00:00.000000001", "2024-01-01 00:00:00.000000002"]
            >>> s_pd = pd.to_datetime(pd.Series(data))
            >>> s_pl = pl.Series(data).str.to_datetime(time_unit="ns")

            We define a library agnostic function:

            >>> def agnostic_total_nanoseconds(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.diff().dt.total_nanoseconds().to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_total_nanoseconds`:

            >>> agnostic_total_nanoseconds(s_pd)
            0    NaN
            1    1.0
            dtype: float64

            >>> agnostic_total_nanoseconds(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [i64]
            [
                    null
                    1
            ]
        )r  rC   r'   r  total_nanosecondsr0   s    r   r  z)SeriesDateTimeNamespace.total_nanoseconds*  s<    Z $$;;!!3366HHJ
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                  |            S )a  Convert a Date/Time/Datetime series into a String series with the given format.

        Arguments:
            format: Format string for converting the datetime to string.

        Returns:
            A new Series with the datetime values formatted as strings according to the specified format.

        Notes:
            Unfortunately, different libraries interpret format directives a bit
            differently.

            - Chrono, the library used by Polars, uses `"%.f"` for fractional seconds,
              whereas pandas and Python stdlib use `".%f"`.
            - PyArrow interprets `"%S"` as "seconds, including fractional seconds"
              whereas most other tools interpret it as "just seconds, as 2 digits".

            Therefore, we make the following adjustments:

            - for pandas-like libraries, we replace `"%S.%f"` with `"%S%.f"`.
            - for PyArrow, we replace `"%S.%f"` with `"%S"`.

            Workarounds like these don't make us happy, and we try to avoid them as
            much as possible, but here we feel like it's the best compromise.

            If you just want to format a date/datetime Series as a local datetime
            string, and have it work as consistently as possible across libraries,
            we suggest using:

            - `"%Y-%m-%dT%H:%M:%S%.f"` for datetimes
            - `"%Y-%m-%d"` for dates

            though note that, even then, different tools may return a different number
            of trailing zeros. Nonetheless, this is probably consistent enough for
            most applications.

            If you have an application where this is not enough, please open an issue
            and let us know.

        Examples:
            >>> from datetime import datetime
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [
            ...     datetime(2020, 3, 1),
            ...     datetime(2020, 4, 1),
            ...     datetime(2020, 5, 1),
            ... ]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            We define a dataframe-agnostic function:

            >>> def agnostic_to_string(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.to_string("%Y/%m/%d").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_to_string`:

            >>> agnostic_to_string(s_pd)
            0    2020/03/01
            1    2020/04/01
            2    2020/05/01
            dtype: object

            >>> agnostic_to_string(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [str]
            [
               "2020/03/01"
               "2020/04/01"
               "2020/05/01"
            ]

            >>> agnostic_to_string(s_pa)  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                "2020/03/01",
                "2020/04/01",
                "2020/05/01"
              ]
            ]
        )r  rC   r'   r  	to_stringr  s     r   r  z!SeriesDateTimeNamespace.to_string[  s>    v $$;;!!3366@@H
 	
r!   c                    | j                   j                  | j                   j                  j                  j	                  |            S )uM  Replace time zone.

        Arguments:
            time_zone: Target time zone.

        Returns:
            A new Series with the specified time zone.

        Examples:
            >>> from datetime import datetime, timezone
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [
            ...     datetime(2024, 1, 1, tzinfo=timezone.utc),
            ...     datetime(2024, 1, 2, tzinfo=timezone.utc),
            ... ]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_replace_time_zone(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.replace_time_zone("Asia/Kathmandu").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_replace_time_zone`:

            >>> agnostic_replace_time_zone(s_pd)
            0   2024-01-01 00:00:00+05:45
            1   2024-01-02 00:00:00+05:45
            dtype: datetime64[ns, Asia/Kathmandu]

            >>> agnostic_replace_time_zone(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [datetime[μs, Asia/Kathmandu]]
            [
                2024-01-01 00:00:00 +0545
                2024-01-02 00:00:00 +0545
            ]

            >>> agnostic_replace_time_zone(s_pa)
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2023-12-31 18:15:00.000000Z,
                2024-01-01 18:15:00.000000Z
              ]
            ]
        )r  rC   r'   r  replace_time_zone)r   	time_zones     r   r  z)SeriesDateTimeNamespace.replace_time_zone  s>    p $$;;!!3366HHS
 	
r!   c                    |d}t        |      | j                  j                  | j                  j                  j                  j                  |            S )u  Convert time zone.

        If converting from a time-zone-naive column, then conversion happens
        as if converting from UTC.

        Arguments:
            time_zone: Target time zone.

        Returns:
            A new Series with the specified time zone.

        Examples:
            >>> from datetime import datetime, timezone
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [
            ...     datetime(2024, 1, 1, tzinfo=timezone.utc),
            ...     datetime(2024, 1, 2, tzinfo=timezone.utc),
            ... ]
            >>> s_pd = pd.Series(data)
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_convert_time_zone(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.convert_time_zone("Asia/Kathmandu").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_convert_time_zone`:

            >>> agnostic_convert_time_zone(s_pd)
            0   2024-01-01 05:45:00+05:45
            1   2024-01-02 05:45:00+05:45
            dtype: datetime64[ns, Asia/Kathmandu]

            >>> agnostic_convert_time_zone(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (2,)
            Series: '' [datetime[μs, Asia/Kathmandu]]
            [
                2024-01-01 05:45:00 +0545
                2024-01-02 05:45:00 +0545
            ]

            >>> agnostic_convert_time_zone(s_pa)
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2024-01-01 00:00:00.000000Z,
                2024-01-02 00:00:00.000000Z
              ]
            ]
        zTarget `time_zone` cannot be `None` in `convert_time_zone`. Please use `replace_time_zone(None)` if you want to remove the time zone.)r   r  rC   r'   r  convert_time_zone)r   r  r,   s      r   r  z)SeriesDateTimeNamespace.convert_time_zone  sV    v  ZCC. $$;;!!3366HHS
 	
r!   c                    |dvrd|d}t        |      | j                  j                  | j                  j                  j                  j                  |            S )a  Return a timestamp in the given time unit.

        Arguments:
            time_unit: {'ns', 'us', 'ms'}
                Time unit.

        Returns:
            A new Series with timestamps in the specified time unit.

        Examples:
            >>> from datetime import date
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [date(2001, 1, 1), None, date(2001, 1, 3)]
            >>> s_pd = pd.Series(data, dtype="datetime64[ns]")
            >>> s_pl = pl.Series(data)
            >>> s_pa = pa.chunked_array([data])

            Let's define a dataframe-agnostic function:

            >>> def agnostic_timestamp(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.dt.timestamp("ms").to_native()

            We can then pass any supported library such as pandas, Polars, or
            PyArrow to `agnostic_timestamp`:

            >>> agnostic_timestamp(s_pd)
            0    9.783072e+11
            1             NaN
            2    9.784800e+11
            dtype: float64

            >>> agnostic_timestamp(s_pl)  # doctest: +NORMALIZE_WHITESPACE
            shape: (3,)
            Series: '' [i64]
            [
                    978307200000
                    null
                    978480000000
            ]

            >>> agnostic_timestamp(s_pa)
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                978307200000,
                null,
                978480000000
              ]
            ]
        >   msnsusz=invalid `time_unit`

Expected one of {'ns', 'us', 'ms'}, got r$   )r   r  rC   r'   r  	timestamp)r   	time_unitr,   s      r   r  z!SeriesDateTimeNamespace.timestamp8  sk    r ..AAJQP  S/!$$;;!!3366@@K
 	
r!   Nr  r  )r   r   r  r  r  r  )r   r   r  r  r  r  )r   r   r  r  r  r  )r  )r   r   r  zLiteral['ns', 'us', 'ms']r  r  )r  r  r  r-   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r8   r!   r   r  r    s    '7
r4
l3
j4
l4
l4
l4
lC
JC
J7
r5
n2
h9
v9
v<
|<
|/
b]
~:
x@
DA
r!   r  c                      e Zd ZddZddZy)r  c                    || _         y r7   r  rd   s     r   r-   zSeriesListNamespace.__init__}  r  r!   c                    | j                   j                  | j                   j                  j                  j	                               S )a  Return the number of elements in each list.

        Null values count towards the total.

        Returns:
            A new series.

        Examples:
            >>> import pandas as pd
            >>> import polars as pl
            >>> import pyarrow as pa
            >>> import narwhals as nw
            >>> from narwhals.typing import IntoSeriesT

            >>> data = [[1, 2], [3, 4, None], None, []]

            Let's define a dataframe-agnostic function:

            >>> def agnostic_list_len(s_native: IntoSeriesT) -> IntoSeriesT:
            ...     s = nw.from_native(s_native, series_only=True)
            ...     return s.list.len().to_native()

            We can then pass pandas / PyArrow / Polars / any other supported library:

            >>> agnostic_list_len(
            ...     pd.Series(data, dtype=pd.ArrowDtype(pa.list_(pa.int64())))
            ... )  # doctest: +SKIP
            0       2
            1       3
            2    <NA>
            3       0
            dtype: int32[pyarrow]

            >>> agnostic_list_len(pl.Series(data))  # doctest: +NORMALIZE_WHITESPACE
            shape: (4,)
            Series: '' [u32]
            [
               2
               3
               null
               0
            ]

            >>> agnostic_list_len(pa.chunked_array([data]))  # doctest: +ELLIPSIS
            <pyarrow.lib.ChunkedArray object at ...>
            [
              [
                2,
                3,
                null,
                0
              ]
            ]
        )r  rC   r'   r   rn   r0   s    r   rn   zSeriesListNamespace.len  s<    n $$;;!!3388<<>
 	
r!   Nr  r  )r  r  r  r-   rn   r8   r!   r   r  r  |  s    '9
r!   r  )+
__future__r   typingr   r   r   r   r   r	   r
   r   r   r   narwhals.dependenciesr   narwhals.dtypesr   narwhals.typingr   narwhals.utilsr   r   r   typesr   numpynppandaspdrK   rQ   typing_extensionsr   r   r   r   r   r   r  r  r  r  r  r8   r!   r   <module>r     s    "            1 + ' 6 ( ( &,%-PK)W[! PK)fV )6#;
/:
) :
zR
GG, R
jo
gg. o
d'=
''* =
r!   