Repository: Zeroto521/my-data-toolkit

Issue:
ENH: New geoaccessor `Index.h3`
<!--
Thanks for contributing a pull request!

Please follow these standard acronyms to start the commit message:

- ENH: enhancement
- BUG: bug fix
- DOC: documentation
- TYP: type annotations
- TST: addition or modification of tests
- MAINT: maintenance commit (refactoring, typos, etc.)
- BLD: change related to building
- REL: related to releasing
- API: an (incompatible) API change
- DEP: deprecate something, or remove a deprecated object
- DEV: development tool or utility
- REV: revert an earlier commit
- PERF: performance improvement
- BOT: always commit via a bot
- CI: related to CI or CD
- CLN: Code cleanup
-->

- [x] closes #779
- [x] whatsnew entry

Think about how to apply h3 accessor to DataFrame.
DataFrame accessor always needs to key in a column name. But using the index could avoid inputting.
So Index accessor h3 as the base, then adapt that to Series and DataFrame.


Discussion:

Resolving patch:
diff --git a/dtoolkit/geoaccessor/geodataframe/to_h3.py b/dtoolkit/geoaccessor/geodataframe/to_h3.py
--- a/dtoolkit/geoaccessor/geodataframe/to_h3.py
+++ b/dtoolkit/geoaccessor/geodataframe/to_h3.py
@@ -1,158 +1,17 @@
-from __future__ import annotations
-
-from typing import Hashable
-
 import geopandas as gpd
-import pandas as pd
+from pandas.util._decorators import doc
 
-from dtoolkit.accessor.dataframe import repeat
-from dtoolkit.accessor.series import len as s_len
-from dtoolkit.geoaccessor.geodataframe.drop_geometry import drop_geometry
-from dtoolkit.geoaccessor.geoseries.to_h3 import points_to_h3
-from dtoolkit.geoaccessor.geoseries.to_h3 import polygons_to_h3
+from dtoolkit.geoaccessor.geoseries import to_h3 as s_to_h3
 from dtoolkit.geoaccessor.register import register_geodataframe_method
 
 
 @register_geodataframe_method
+@doc(s_to_h3, klass="GeoDataFrame")
 def to_h3(
     df: gpd.GeoDataFrame,
     /,
     resolution: int,
-    drop: bool = True,
-    name: Hashable = "h3",
     int_dtype: bool = True,
-) -> pd.DataFrame | gpd.GeoDataFrame:
-    """
-    Convert Point to containing H3 cell index.
-
-    Parameters
-    ----------
-    resolution : int
-        H3 resolution.
-
-    drop : bool, default True
-        Whether to drop the geometry column.
-
-    name : Hashable, default "h3"
-        Name of the column to store the H3 cell index.
-
-    int_dtype : bool, default True
-        If True, use ``h3.api.numpy_int`` else use ``h3.api.basic_str``.
-
-    Returns
-    -------
-    DataFrame or GeoDataFrame
-        DataFrame if drop is True else GeoDataFrame.
-
-    Raises
-    ------
-    ModuleNotFoundError
-        If don't have module named 'h3'.
-
-    TypeError
-        If the geometry is not Point.
-
-    ValueError
-        If the CRS is not WGS84 or EPSG:4326.
-
-    See Also
-    --------
-    h3.latlon_to_h3
-    h3.polygon_to_cells
-    dtoolkit.geoaccessor.geoseries.to_h3
-
-    Examples
-    --------
-    >>> import dtoolkit.geoaccessor
-    >>> import pandas as pd
-
-    Points to h3 indexes.
-
-    >>> df = pd.DataFrame({"x": [122, 100], "y": [55, 1]}).from_xy('x', 'y', crs=4326)
-    >>> df
-         x   y                    geometry
-    0  122  55  POINT (122.00000 55.00000)
-    1  100   1   POINT (100.00000 1.00000)
-    >>> df.to_h3(8)
-         x   y                  h3
-    0  122  55  612845052823076863
-    1  100   1  614269156845420543
-
-    Keep the geometry column.
-
-    >>> df.to_h3(8, drop=False)
-         x   y                    geometry                  h3
-    0  122  55  POINT (122.00000 55.00000)  612845052823076863
-    1  100   1   POINT (100.00000 1.00000)  614269156845420543
-
-    Polygons to h3 indexes.
-
-    >>> df = pd.DataFrame(
-    ...     {
-    ...         "label": ["a", "b"],
-    ...         "wkt": [
-    ...             "POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))",
-    ...             "POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))",
-    ...         ],
-    ...     },
-    ... ).from_wkt("wkt", crs=4326).drop(columns="wkt")
-    >>> df
-      label                                           geometry
-    0     a  POLYGON ((1.00000 0.00000, 1.00000 1.00000, 0....
-    1     b  POLYGON ((2.00000 1.00000, 2.00000 2.00000, 1....
-    >>> df.to_h3(4)
-      label                  h3
-    0     a  596538839648960511
-    0     a  596538693620072447
-    0     a  596538685030137855
-    0     a  596538848238895103
-    0     a  596537920525959167
-    0     a  596538813879156735
-    0     a  596538856828829695
-    0     a  596538805289222143
-    1     b  596538229763604479
-    1     b  596537946295762943
-    1     b  596540780974178303
-    1     b  596540729434570751
-    1     b  596540772384243711
-    1     b  596538212583735295
-    1     b  596540763794309119
-    1     b  596537954885697535
-    1     b  596540746614439935
-    1     b  596538195403866111
-    1     b  596541030082281471
-
-    Also support str (hexadecimal) format.
-
-    >>> df = pd.DataFrame({"x": [122, 100], "y": [55, 1]}).from_xy('x', 'y', crs=4326)
-    >>> df
-         x   y                    geometry
-    0  122  55  POINT (122.00000 55.00000)
-    1  100   1   POINT (100.00000 1.00000)
-    >>> df.to_h3(8, int_dtype=False)
-         x   y               h3
-    0  122  55  88143541bdfffff
-    1  100   1  886528b2a3fffff
-    """
-
-    if df.crs != 4326:
-        raise ValueError(f"Only support 'EPSG:4326' CRS, but got {df.crs!r}.")
-
-    if all(df.geom_type == "Point"):
-        h3 = points_to_h3(
-            df.geometry,
-            resolution=resolution,
-            int_dtype=int_dtype,
-        ).rename(name)
-    elif all(df.geom_type == "Polygon"):
-        h3_list = polygons_to_h3(
-            df.geometry,
-            resolution=resolution,
-            int_dtype=int_dtype,
-        )
-        h3 = h3_list.explode().rename(name)
-        df = repeat(df, s_len(h3_list))
-    else:
-        raise TypeError("Only support 'Point' or 'Polygon' geometry type.")
+) -> gpd.GeoDataFrame:
 
-    return pd.concat((drop_geometry(df) if drop else df, h3), axis=1)
+    return s_to_h3(df, resolution=resolution, int_dtype=int_dtype)
diff --git a/dtoolkit/geoaccessor/geoseries/to_h3.py b/dtoolkit/geoaccessor/geoseries/to_h3.py
--- a/dtoolkit/geoaccessor/geoseries/to_h3.py
+++ b/dtoolkit/geoaccessor/geoseries/to_h3.py
@@ -1,26 +1,20 @@
-from __future__ import annotations
-
-from typing import Hashable
-
 import geopandas as gpd
-import pandas as pd
+from pandas._libs.reshape import explode
+from pandas.util._decorators import doc
 
 from dtoolkit.accessor.series import getattr as s_getattr
-from dtoolkit.accessor.series import len as s_len
 from dtoolkit.geoaccessor.geoseries.xy import xy
 from dtoolkit.geoaccessor.register import register_geoseries_method
-from dtoolkit.geoaccessor.series import to_geoframe
 
 
 @register_geoseries_method
+@doc(klass="GeoSeries")
 def to_h3(
     s: gpd.GeoSeries,
     /,
     resolution: int,
-    drop: bool = True,
-    name: Hashable = "h3",
     int_dtype: bool = True,
-) -> pd.Series | gpd.GeoDataFrame:
+) -> gpd.GeoSeries:
     """
     Convert Point or Polygon to H3 cell index.
 
@@ -29,20 +23,13 @@ def to_h3(
     resolution : int
         H3 resolution.
 
-    name : Hashable, default "h3"
-        Name of the column to store the H3 cell index. If ``name`` is None, there will
-        use ``s.name`` as the column name.
-
-    drop : bool, default True
-        Whether to drop the geometry column.
-
     int_dtype : bool, default True
         If True, use ``h3.api.numpy_int`` else use ``h3.api.basic_str``.
 
     Returns
     -------
-    Series or GeoDataFrame
-        Series if drop is True else GeoDataFrame.
+    {klass}
+        With H3 cell as the its index.
 
     Raises
     ------
@@ -53,13 +40,14 @@ def to_h3(
         If the geometry type is not Point or Polygon.
 
     ValueError
-        - If the CRS is not WGS84 or EPSG:4326.
-        - If ``drop=False`` but ``name=None`` or ``s.name=None``.
+        If the CRS is not WGS84 or EPSG:4326.
 
     See Also
     --------
     h3.latlon_to_h3
     h3.polygon_to_cells
+    dtoolkit.geoaccessor.series.H3
+    dtoolkit.geoaccessor.geoseries.to_h3
     dtoolkit.geoaccessor.geodataframe.to_h3
 
     Examples
@@ -69,81 +57,64 @@ def to_h3(
 
     Points to h3 indexes.
 
-    >>> s = pd.Series(
-    ...     [
-    ...         "POINT (122 55)",
-    ...         "POINT (100 1)",
-    ...     ],
-    ...     name="wkt",
-    ... ).from_wkt(crs=4326).geometry
-    >>> s
-    0    POINT (122.00000 55.00000)
-    1     POINT (100.00000 1.00000)
-    Name: geometry, dtype: geometry
-    >>> s.to_h3(8)
-    0    612845052823076863
-    1    614269156845420543
-    dtype: int64
-
-    Keep the geometry column.
-
-    >>> s.to_h3(8, drop=False)
-                         h3                    geometry
-    0    612845052823076863  POINT (122.00000 55.00000)
-    1    614269156845420543   POINT (100.00000 1.00000)
+    >>> df = pd.DataFrame({{"x": [122, 100], "y": [55, 1]}}).from_xy('x', 'y', crs=4326)
+    >>> df
+         x   y                    geometry
+    0  122  55  POINT (122.00000 55.00000)
+    1  100   1   POINT (100.00000 1.00000)
+    >>> df.to_h3(8)
+                          x   y                    geometry
+    612845052823076863  122  55  POINT (122.00000 55.00000)
+    614269156845420543  100   1   POINT (100.00000 1.00000)
 
     Polygons to h3 indexes.
 
-    >>> s = pd.Series(
-    ...     [
-    ...         "POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))",
-    ...         "POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))",
-    ...     ],
-    ...     name="wkt",
-    ... ).from_wkt(crs=4326).geometry
-    >>> s
-    0    POLYGON ((1.00000 0.00000, 1.00000 1.00000, 0....
-    1    POLYGON ((2.00000 1.00000, 2.00000 2.00000, 1....
-    Name: geometry, dtype: geometry
-    >>> s.to_h3(4)
-    0    596538839648960511
-    0    596538693620072447
-    0    596538685030137855
-    0    596538848238895103
-    0    596537920525959167
-    0    596538813879156735
-    0    596538856828829695
-    0    596538805289222143
-    1    596538229763604479
-    1    596537946295762943
-    1    596540780974178303
-    1    596540729434570751
-    1    596540772384243711
-    1    596538212583735295
-    1    596540763794309119
-    1    596537954885697535
-    1    596540746614439935
-    1    596538195403866111
-    1    596541030082281471
-    Name: geometry, dtype: object
+    >>> df = pd.DataFrame(
+    ...     {{
+    ...         "label": ["a", "b"],
+    ...         "wkt": [
+    ...             "POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))",
+    ...             "POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))",
+    ...         ],
+    ...     }},
+    ... ).from_wkt("wkt", crs=4326).drop(columns="wkt")
+    >>> df
+      label                                           geometry
+    0     a  POLYGON ((1.00000 0.00000, 1.00000 1.00000, 0....
+    1     b  POLYGON ((2.00000 1.00000, 2.00000 2.00000, 1....
+    >>> df.to_h3(4)
+                       label                             geometry
+    596538839648960511     a  POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))
+    596538693620072447     a  POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))
+    596538685030137855     a  POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))
+    596538848238895103     a  POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))
+    596537920525959167     a  POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))
+    596538813879156735     a  POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))
+    596538856828829695     a  POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))
+    596538805289222143     a  POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))
+    596538229763604479     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
+    596537946295762943     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
+    596540780974178303     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
+    596540729434570751     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
+    596540772384243711     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
+    596538212583735295     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
+    596540763794309119     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
+    596537954885697535     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
+    596540746614439935     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
+    596538195403866111     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
+    596541030082281471     b  POLYGON ((2 1, 2 2, 1 2, 1 1, 2 1))
 
     Also support str (hexadecimal) format.
 
-    >>> s = pd.Series(
-    ...     [
-    ...         "POINT (122 55)",
-    ...         "POINT (100 1)",
-    ...     ],
-    ...     name="wkt",
-    ... ).from_wkt(crs=4326).geometry
-    >>> s
-    0    POINT (122.00000 55.00000)
-    1     POINT (100.00000 1.00000)
-    Name: geometry, dtype: geometry
-    >>> s.to_h3(8, int_dtype=False)
-    0    88143541bdfffff
-    1    886528b2a3fffff
-    dtype: object
+    >>> df = pd.DataFrame({{"x": [122, 100], "y": [55, 1]}}).from_xy('x', 'y', crs=4326)
+    >>> df
+         x   y                    geometry
+    0  122  55  POINT (122.00000 55.00000)
+    1  100   1   POINT (100.00000 1.00000)
+    >>> df.to_h3(8, int_dtype=False)
+                       x   y                    geometry
+    88143541bdfffff  122  55  POINT (122.00000 55.00000)
+    886528b2a3fffff  100   1   POINT (100.00000 1.00000)
     """
 
     # TODO: Advices for h3-pandas
@@ -151,54 +122,33 @@ def to_h3(
     # 2. compat with h3-py 4
     # 3. requires crs is 4326
     # 4. consider h3-py as the accessor of Series
-    # 6. Speed up creating points / polygons via pygeos
+    # 6. Speed up creating points / polygons via shapely 2.x
+
+    if int_dtype:
+        import h3.api.numpy_int as h3
+    else:
+        import h3.api.basic_str as h3
 
     if s.crs != 4326:
         raise ValueError(f"Only support 'EPSG:4326' CRS, but got {s.crs!r}.")
-    if not drop and name is None and s.name is None:
-        raise ValueError(
-            "to keep the original data requires setting the 'name' of "
-            f"{s.__class__.__name__!r} or 'name'.",
-        )
 
     if all(s.geom_type == "Point"):
-        h3 = points_to_h3(s, resolution=resolution, int_dtype=int_dtype)
+        # TODO: Use `latlon_to_h3` instead of `geo_to_h3`
+        # While h3-py release 4, `latlon_to_h3` is not available.
+        return s.set_axis(
+            xy(s.geometry, reverse=True, frame=False, name=None)
+            .apply(lambda yx: getattr(h3, "geo_to_h3")(*yx, resolution))
+            .to_numpy(),
+        )
     elif all(s.geom_type == "Polygon"):
-        h3_list = polygons_to_h3(s, resolution=resolution, int_dtype=int_dtype)
-        h3 = h3_list.explode()
-        s = s.repeat(s_len(h3_list))
-    else:
-        raise TypeError("Only support 'Point' or 'Polygon' geometry type.")
-
-    return h3 if drop else to_geoframe(h3.rename(name or s.name), geometry=s)
-
-
-def points_to_h3(s: gpd.GeoSeries, /, resolution: int, int_dtype: bool) -> pd.Series:
-    # TODO: Use `latlon_to_h3` instead of `geo_to_h3`
-    # While h3-py release 4, `latlon_to_h3` is not available.
-    method = method_from_h3("geo_to_h3", int_dtype=int_dtype)
-
-    return xy(s, reverse=True, frame=False, name=None).apply(
-        lambda yx: method(*yx, resolution),
-    )
-
-
-def polygons_to_h3(s: gpd.GeoSeries, /, resolution: int, int_dtype: bool) -> pd.Series:
-    # TODO: Use `polygon_to_cells` instead of `geo_to_h3`
-    # While h3-py release 4, `polygon_to_cells` is not available.
-
-    # If `geo_json_conformant` is True, the coordinate could be (lon, lat).
-    return s_getattr(s, "__geo_interface__").apply(
-        method_from_h3("polyfill", int_dtype=int_dtype),
-        res=resolution,
-        geo_json_conformant=True,
-    )
-
-
-def method_from_h3(method: str, int_dtype: bool = True) -> callable:
-    if int_dtype:
-        import h3.api.numpy_int as h3
-    else:
-        import h3.api.basic_str as h3
+        # TODO: Use `polygon_to_cells` instead of `geo_to_h3`
+        # While h3-py release 4, `polygon_to_cells` is not available.
+        # If `geo_json_conformant` is True, the coordinate could be (lon, lat).
+        h3, counts = explode(
+            s_getattr(s.geometry, "__geo_interface__")
+            .apply(getattr(h3, "polyfill"), res=resolution, geo_json_conformant=True)
+            .to_numpy(),
+        )
+        return s.repeat(counts).set_axis(h3)
 
-    return getattr(h3, method)
+    raise TypeError("Only support 'Point' or 'Polygon' geometry type.")


Test patch:
diff --git a/test/geoaccessor/geodataframe/test_to_h3.py b/test/geoaccessor/geodataframe/test_to_h3.py
deleted file mode 100644
--- a/test/geoaccessor/geodataframe/test_to_h3.py
+++ /dev/null
@@ -1,43 +0,0 @@
-import pandas as pd
-import pytest
-
-from dtoolkit.geoaccessor.geodataframe import to_h3
-
-
-pytest.importorskip("h3")
-
-
-@pytest.mark.parametrize(
-    "df, resolution, drop, name, error",
-    [
-        # crs != 4326
-        (
-            pd.DataFrame({"x": [122, 100], "y": [55, 1]}).from_xy("x", "y"),
-            8,
-            True,
-            None,
-            ValueError,
-        ),
-        # geometry type is not Point or Polygon
-        (
-            pd.DataFrame(
-                {
-                    "label": ["a", "b"],
-                    "wkt": [
-                        "LINESTRING (122 100, 55 1)",
-                        "LINESTRING (122 55, 100 1)",
-                    ],
-                },
-            )
-            .from_wkt("wkt", crs=4326)
-            .drop(columns="wkt"),
-            8,
-            True,
-            None,
-            TypeError,
-        ),
-    ],
-)
-def test_error(df, resolution, drop, name, error):
-    with pytest.raises(error):
-        to_h3(df, resolution=resolution, drop=drop, name=name)
diff --git a/test/geoaccessor/geoseries/test_to_h3.py b/test/geoaccessor/geoseries/test_to_h3.py
--- a/test/geoaccessor/geoseries/test_to_h3.py
+++ b/test/geoaccessor/geoseries/test_to_h3.py
@@ -1,7 +1,9 @@
 import geopandas as gpd
 import pytest
+from geopandas.testing import assert_geoseries_equal
 from shapely import LineString
 from shapely import Point
+from shapely import Polygon
 
 from dtoolkit.geoaccessor.geoseries import to_h3
 
@@ -10,34 +12,101 @@
 
 
 @pytest.mark.parametrize(
-    "s, resolution, drop, name, error",
+    "s, error",
     [
         # crs != 4326
         (
             gpd.GeoSeries([Point(122, 55), Point(100, 1)]),
-            8,
-            True,
-            None,
             ValueError,
         ),
-        # s.name is None and name is None
+        # geometry type is not Point or Polygon
+        (
+            gpd.GeoSeries([LineString([(122, 55), (100, 1)])], crs=4326),
+            TypeError,
+        ),
+    ],
+)
+def test_error(s, error):
+    with pytest.raises(error):
+        to_h3(s, 8)
+
+
+@pytest.mark.parametrize(
+    "s, resolution, int_dtype, expected",
+    # NOTE: the `s` argument of the `GeoSeries.to_h3` could receive a GeoSeries or
+    # a GeoDataFrame
+    [
+        # GeoSeries with Point geometries working
         (
             gpd.GeoSeries([Point(122, 55), Point(100, 1)], crs=4326),
             8,
-            False,
-            None,
-            ValueError,
+            True,
+            gpd.GeoSeries(
+                [Point(122, 55), Point(100, 1)],
+                index=[612845052823076863, 614269156845420543],
+                crs=4326,
+            ),
         ),
-        # geometry type is not Point or Polygon
+        # GeoSeries with Polygon geometries working
         (
-            gpd.GeoSeries([LineString([(122, 55), (100, 1)])], crs=4326),
-            8,
+            gpd.GeoSeries(
+                [
+                    Polygon(((1, 0), (1, 1), (0, 1), (0, 0), (1, 0))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                ],
+                crs=4326,
+            ),
+            4,
             True,
-            None,
-            TypeError,
+            gpd.GeoSeries(
+                [
+                    Polygon(((1, 0), (1, 1), (0, 1), (0, 0), (1, 0))),
+                    Polygon(((1, 0), (1, 1), (0, 1), (0, 0), (1, 0))),
+                    Polygon(((1, 0), (1, 1), (0, 1), (0, 0), (1, 0))),
+                    Polygon(((1, 0), (1, 1), (0, 1), (0, 0), (1, 0))),
+                    Polygon(((1, 0), (1, 1), (0, 1), (0, 0), (1, 0))),
+                    Polygon(((1, 0), (1, 1), (0, 1), (0, 0), (1, 0))),
+                    Polygon(((1, 0), (1, 1), (0, 1), (0, 0), (1, 0))),
+                    Polygon(((1, 0), (1, 1), (0, 1), (0, 0), (1, 0))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                    Polygon(((2, 1), (2, 2), (1, 2), (1, 1), (2, 1))),
+                ],
+                index=[
+                    596538839648960511,
+                    596538693620072447,
+                    596538685030137855,
+                    596538848238895103,
+                    596537920525959167,
+                    596538813879156735,
+                    596538856828829695,
+                    596538805289222143,
+                    596538229763604479,
+                    596537946295762943,
+                    596540780974178303,
+                    596540729434570751,
+                    596540772384243711,
+                    596538212583735295,
+                    596540763794309119,
+                    596537954885697535,
+                    596540746614439935,
+                    596538195403866111,
+                    596541030082281471,
+                ],
+                crs=4326,
+            ),
         ),
     ],
 )
-def test_error(s, resolution, drop, name, error):
-    with pytest.raises(error):
-        to_h3(s, resolution=resolution, drop=drop, name=name)
+def test_work(s, resolution, int_dtype, expected):
+    result = to_h3(s, resolution=resolution, int_dtype=int_dtype)
+
+    assert_geoseries_equal(result, expected)