Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ValueError using polyfill + h3_to_geo_boundary #32

Open
CarlaFernandez opened this issue Apr 17, 2024 · 2 comments
Open

ValueError using polyfill + h3_to_geo_boundary #32

CarlaFernandez opened this issue Apr 17, 2024 · 2 comments

Comments

@CarlaFernandez
Copy link

Intro

I want to fill a polygon with hexagons of a given resolution and then get the boundaries for those hexagons.
My code is the following:

import h3
import h3pandas

def generate_grid(region_bounds: gpd.GeoDataFrame, resolution=9) -> pd.DataFrame:
    grid = region_bounds.h3.polyfill(resolution, explode=True)
    grid = grid.drop('geometry', axis=1)
    grid = grid.rename(columns={'h3_polyfill': 'h3'})
    # grid = grid.set_index('h3')
    # Convert H3 indexes to their geometric boundaries
    grid['geometry'] = grid.h3.h3_to_geo_boundary()
    return grid

pp_cs_gdf = gpd.read_file('sample_error.geojson')
grid_9 = generate_grid(pp_cs_gdf, 9)

Error

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3pandas/util/decorator.py:27, in catch_invalid_h3_address.<locals>.safe_f(*args, **kwargs)
     26 try:
---> 27     return f(*args, **kwargs)
     28 except (TypeError, ValueError, H3CellError) as e:

File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3/api/_api_template.py:294, in _API_FUNCTIONS.h3_to_geo_boundary(self, h, geo_json)
    277 """
    278 Return tuple of lat/lng pairs describing the cell boundary.
    279 
   (...)
    292 tuple of (float, float) tuples
    293 """
--> 294 return _cy.cell_boundary(self._in_scalar(h), geo_json)

TypeError: Argument 'h' has incorrect type (expected str, got int)

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
Cell In[120], line 13
     10     grid['geometry'] = grid.h3.h3_to_geo_boundary()
     11     return grid
---> 13 grid_9 = generate_grid(pp_cs_gdf, 9)

Cell In[120], line 10, in generate_grid(region_bounds, resolution)
      7 grid = grid.rename(columns={'h3_polyfill': 'h3'})
      8 # grid = grid.set_index('h3')
      9 # Convert H3 indexes to their geometric boundaries
---> 10 grid['geometry'] = grid.h3.h3_to_geo_boundary()
     11 return grid

File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3pandas/h3pandas.py:160, in H3Accessor.h3_to_geo_boundary(self)
    139 def h3_to_geo_boundary(self) -> GeoDataFrame:
    140     """Add `geometry` with H3 hexagons to the DataFrame. Assumes H3 index.
    141 
    142     Returns
   (...)
    158     881e2659c3fffff    1  POLYGON ((14.99201 51.00565, 14.98973 51.00133...
    159     """
--> 160     return self._apply_index_assign(
    161         wrapped_partial(h3.h3_to_geo_boundary, geo_json=True),
    162         "geometry",
    163         lambda x: shapely.geometry.Polygon(x),
    164         lambda x: gpd.GeoDataFrame(x, crs="epsg:4326"),
    165     )

File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3pandas/h3pandas.py:836, in H3Accessor._apply_index_assign(self, func, column_name, processor, finalizer)
    817 """Helper method. Applies `func` to index and assigns the result to `column`.
    818 
    819 Parameters
   (...)
    833 If using `finalizer`, can return anything the `finalizer` returns.
    834 """
    835 func = catch_invalid_h3_address(func)
--> 836 result = [processor(func(h3address)) for h3address in self._df.index]
    837 assign_args = {column_name: result}
    838 return finalizer(self._df.assign(**assign_args))

File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3pandas/h3pandas.py:836, in <listcomp>(.0)
    817 """Helper method. Applies `func` to index and assigns the result to `column`.
    818 
    819 Parameters
   (...)
    833 If using `finalizer`, can return anything the `finalizer` returns.
    834 """
    835 func = catch_invalid_h3_address(func)
--> 836 result = [processor(func(h3address)) for h3address in self._df.index]
    837 assign_args = {column_name: result}
    838 return finalizer(self._df.assign(**assign_args))

File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3pandas/util/decorator.py:32, in catch_invalid_h3_address.<locals>.safe_f(*args, **kwargs)
     30 message += f"\nCaller: {f.__name__}({_print_signature(*args, **kwargs)})"
     31 message += f"\nOriginal error: {repr(e)}"
---> 32 raise ValueError(message)

ValueError: H3 method raised an error. Is the H3 address correct?
Caller: h3_to_geo_boundary(17894)
Original error: TypeError("Argument 'h' has incorrect type (expected str, got int)")

Reproduce

  • h3==3.7.7
  • h3pandas===0.2.6
  • I attach a sample of the dataframe I'm using:
    sample_error.zip
@CarlaFernandez CarlaFernandez changed the title ValueError using h3_polyfill + h3_to_geo_boundary ValueError using polyfill + h3_to_geo_boundary Apr 17, 2024
@ajfriend
Copy link

While the interface might not be as integrated as h3pandas, I did recently put up an example notebook that does exactly this with the new v4.0 beta of the plain h3-py library: https://uber.github.io/h3-py/polygon_tutorial.html

@CarlaFernandez
Copy link
Author

So I managed to get it working for one polygon by changing my function like so:

def generate_grid(region_bounds: gpd.GeoDataFrame, resolution=9) -> pd.DataFrame:
    grid = region_bounds.h3.polyfill(resolution, explode=True)

    grid = grid.set_index('h3_polyfill')
    grid = grid.h3.h3_to_geo_boundary()

    return grid

If I input more than one polygon, now the error is different:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3pandas/util/decorator.py:27, in catch_invalid_h3_address.<locals>.safe_f(*args, **kwargs)
     26 try:
---> 27     return f(*args, **kwargs)
     28 except (TypeError, ValueError, H3CellError) as e:

File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3/api/_api_template.py:294, in _API_FUNCTIONS.h3_to_geo_boundary(self, h, geo_json)
    277 """
    278 Return tuple of lat/lng pairs describing the cell boundary.
    279 
   (...)
    292 tuple of (float, float) tuples
    293 """
--> 294 return _cy.cell_boundary(self._in_scalar(h), geo_json)

TypeError: Argument 'h' has incorrect type (expected str, got float)

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
Cell In[24], line 14
     10     grid = grid.h3.h3_to_geo_boundary()
     12     return grid
---> 14 grid_9 = generate_grid(pp_cs_gdf[:2], 9)

Cell In[24], line 10, in generate_grid(region_bounds, resolution)
      8 grid = grid.set_index('h3_polyfill')
      9 display(grid)
---> 10 grid = grid.h3.h3_to_geo_boundary()
     12 return grid

File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3pandas/h3pandas.py:160, in H3Accessor.h3_to_geo_boundary(self)
    139 def h3_to_geo_boundary(self) -> GeoDataFrame:
    140     """Add `geometry` with H3 hexagons to the DataFrame. Assumes H3 index.
    141 
    142     Returns
   (...)
    158     881e2659c3fffff    1  POLYGON ((14.99201 51.00565, 14.98973 51.00133...
    159     """
--> 160     return self._apply_index_assign(
    161         wrapped_partial(h3.h3_to_geo_boundary, geo_json=True),
    162         "geometry",
    163         lambda x: shapely.geometry.Polygon(x),
    164         lambda x: gpd.GeoDataFrame(x, crs="epsg:4326"),
    165     )

File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3pandas/h3pandas.py:836, in H3Accessor._apply_index_assign(self, func, column_name, processor, finalizer)
    817 """Helper method. Applies `func` to index and assigns the result to `column`.
    818 
    819 Parameters
   (...)
    833 If using `finalizer`, can return anything the `finalizer` returns.
    834 """
    835 func = catch_invalid_h3_address(func)
--> 836 result = [processor(func(h3address)) for h3address in self._df.index]
    837 assign_args = {column_name: result}
    838 return finalizer(self._df.assign(**assign_args))

File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3pandas/h3pandas.py:836, in <listcomp>(.0)
    817 """Helper method. Applies `func` to index and assigns the result to `column`.
    818 
    819 Parameters
   (...)
    833 If using `finalizer`, can return anything the `finalizer` returns.
    834 """
    835 func = catch_invalid_h3_address(func)
--> 836 result = [processor(func(h3address)) for h3address in self._df.index]
    837 assign_args = {column_name: result}
    838 return finalizer(self._df.assign(**assign_args))

File /anaconda/envs/azureml_py310_sdkv2/lib/python3.10/site-packages/h3pandas/util/decorator.py:32, in catch_invalid_h3_address.<locals>.safe_f(*args, **kwargs)
     30 message += f"\nCaller: {f.__name__}({_print_signature(*args, **kwargs)})"
     31 message += f"\nOriginal error: {repr(e)}"
---> 32 raise ValueError(message)

ValueError: H3 method raised an error. Is the H3 address correct?
Caller: h3_to_geo_boundary(nan)
Original error: TypeError("Argument 'h' has incorrect type (expected str, got float)")

When I display the grid, the h3_polyfill result contains NaN, and that seems to be the cause:
image

Any idea why this NaN would appear?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants