GeoDataFrame Value Error: 'data' should be a 1-dimensional array of geometry objects'

GeoDataFrame Value Error: 'data' should be a 1-dimensional array of geometry objects'

我想使用 nearest_edges-function 用 osmnx 量化一些地理位置。当 运行 此代码时我收到一条值错误消息并且不知道我做错了什么:

# project graph and points
G_proj = ox.project_graph(G)
gdf_loc_p = gdf_loc["geometry"].to_crs(G_proj.graph["crs"])

ne, d = ox.nearest_edges(
    G_proj, X=gdf_loc_p.x.values, Y=gdf_loc_p.y.values, return_dist=True
)

# reindex points based on results from nearest_edges
gdf_loc = (
    gdf_loc.set_index(pd.MultiIndex.from_tuples(ne, names=["u", "v", "key"]))
    .assign(distance=d)
    .sort_index()
)

# join geometry from edges back to points
# aggregate so have number of accidents on each edge
gdf_bad_roads = (
    gdf_edges.join(gdf_loc, rsuffix="_loc", how="inner")
    .groupby(["u", "v", "key"])
    .agg(geometry = ("geometry", "first"), number=("osmid", "size"))
    .set_crs(gdf_edges.crs)
)

当 运行 时,它在 .agg(geometry)# we require a list, but not a 'str' 行中告诉我,从那里开始出现更多导致值错误 data' should be a 1-dimensional array of geometry objects 的问题。我附上了整个追溯。感谢您的帮助!

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/var/folders/jy/1f2tlvb965g30zhw9q3cvdw07r5rb_/T/ipykernel_82991/3621029527.py in <module>
      2 # aggregate so have number of accidents on each edge
      3 gdf_bad_roads = (
----> 4     gdf_edges.join(gdf_loc, rsuffix="_loc", how="inner")
      5     .groupby(["u", "v", "key"])
      6     .agg(geometry = ("geometry", "first"), number=("osmid", "size"))

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/groupby/generic.py in aggregate(self, func, engine, engine_kwargs, *args, **kwargs)
    977 
    978         op = GroupByApply(self, func, args, kwargs)
--> 979         result = op.agg()
    980         if not is_dict_like(func) and result is not None:
    981             return result

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/apply.py in agg(self)
    159 
    160         if is_dict_like(arg):
--> 161             return self.agg_dict_like()
    162         elif is_list_like(arg):
    163             # we require a list, but not a 'str'

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/apply.py in agg_dict_like(self)
    457 
    458             axis = 0 if isinstance(obj, ABCSeries) else 1
--> 459             result = concat(
    460                 {k: results[k] for k in keys_to_use}, axis=axis, keys=keys_to_use
    461             )

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/util/_decorators.py in wrapper(*args, **kwargs)
    309                     stacklevel=stacklevel,
    310                 )
--> 311             return func(*args, **kwargs)
    312 
    313         return wrapper

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/reshape/concat.py in concat(objs, axis, join, ignore_index, keys, levels, names, verify_integrity, sort, copy)
    305     )
    306 
--> 307     return op.get_result()
    308 
    309 

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/reshape/concat.py in get_result(self)
    537 
    538             cons = sample._constructor
--> 539             return cons(new_data).__finalize__(self, method="concat")
    540 
    541     def _get_result_dim(self) -> int:

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/geopandas/geodataframe.py in __init__(self, data, geometry, crs, *args, **kwargs)
    155             try:
    156                 if (
--> 157                     hasattr(self["geometry"].values, "crs")
    158                     and self["geometry"].values.crs
    159                     and crs

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/geopandas/geodataframe.py in __getitem__(self, key)
   1325         GeoDataFrame.
   1326         """
-> 1327         result = super().__getitem__(key)
   1328         geo_col = self._geometry_column_name
   1329         if isinstance(result, Series) and isinstance(result.dtype, GeometryDtype):

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/frame.py in __getitem__(self, key)
   3424             if self.columns.is_unique and key in self.columns:
   3425                 if isinstance(self.columns, MultiIndex):
-> 3426                     return self._getitem_multilevel(key)
   3427                 return self._get_item_cache(key)
   3428 

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/frame.py in _getitem_multilevel(self, key)
   3511             result_columns = maybe_droplevels(new_columns, key)
   3512             if self._is_mixed_type:
-> 3513                 result = self.reindex(columns=new_columns)
   3514                 result.columns = result_columns
   3515             else:

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/util/_decorators.py in wrapper(*args, **kwargs)
    322         @wraps(func)
    323         def wrapper(*args, **kwargs) -> Callable[..., Any]:
--> 324             return func(*args, **kwargs)
    325 
    326         kind = inspect.Parameter.POSITIONAL_OR_KEYWORD

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/frame.py in reindex(self, *args, **kwargs)
   4770         kwargs.pop("axis", None)
   4771         kwargs.pop("labels", None)
-> 4772         return super().reindex(**kwargs)
   4773 
   4774     @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "labels"])

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/generic.py in reindex(self, *args, **kwargs)
   4816 
   4817         # perform the reindex on the axes
-> 4818         return self._reindex_axes(
   4819             axes, level, limit, tolerance, method, fill_value, copy
   4820         ).__finalize__(self, method="reindex")

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/frame.py in _reindex_axes(self, axes, level, limit, tolerance, method, fill_value, copy)
   4589         columns = axes["columns"]
   4590         if columns is not None:
-> 4591             frame = frame._reindex_columns(
   4592                 columns, method, copy, level, fill_value, limit, tolerance
   4593             )

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/frame.py in _reindex_columns(self, new_columns, method, copy, level, fill_value, limit, tolerance)
   4634             new_columns, method=method, level=level, limit=limit, tolerance=tolerance
   4635         )
-> 4636         return self._reindex_with_indexers(
   4637             {1: [new_columns, indexer]},
   4638             copy=copy,

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/pandas/core/generic.py in _reindex_with_indexers(self, reindexers, fill_value, copy, allow_dups)
   4895             new_data = new_data.copy()
   4896 
-> 4897         return self._constructor(new_data).__finalize__(self)
   4898 
   4899     def filter(

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/geopandas/geodataframe.py in __init__(self, data, geometry, crs, *args, **kwargs)
    162                     _crs_mismatch_warning()
    163                     # TODO: raise error in 0.9 or 0.10.
--> 164                 self["geometry"] = _ensure_geometry(self["geometry"].values, crs)
    165             except TypeError:
    166                 pass

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/geopandas/geodataframe.py in _ensure_geometry(data, crs)
     44             return GeoSeries(out, index=data.index, name=data.name)
     45         else:
---> 46             out = from_shapely(data, crs=crs)
     47             return out
     48 

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/geopandas/array.py in from_shapely(data, crs)
    149 
    150     """
--> 151     return GeometryArray(vectorized.from_shapely(data), crs=crs)
    152 
    153 

~/opt/anaconda3/envs/pyproj_env/lib/python3.10/site-packages/geopandas/array.py in __init__(self, data, crs)
    278             )
    279         elif not data.ndim == 1:
--> 280             raise ValueError(
    281                 "'data' should be a 1-dimensional array of geometry objects."
    282             )

ValueError: 'data' should be a 1-dimensional array of geometry objects.

编辑:谢谢!不幸的是它不起作用。我将 Python 降级到 3.9(并将 Panda 升级到 1.4,但有同样的问题)。我也添加了其他代码的回溯。


----
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [4], in <cell line: 4>()
      2 gdf_bad_roads = gdf_edges.join(gdf_loc, rsuffix="_loc", how="inner")
      3 # aggregate so have number of accidents on each edge
----> 4 gdf_bad_roads_agg = gdf_bad_roads.groupby(["u", "v", "key"]).agg(
      5     geometry=("geometry", "first"), number=("osmid", "size")
      6 ).set_crs(gdf_edges.crs)
      8 print(f"""
      9 pandas: {pd.__version__}
     10 geopandas: {gpd.__version__}
     11 osmnx: {ox.__version__}""")

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/groupby/generic.py:869, in DataFrameGroupBy.aggregate(self, func, engine, engine_kwargs, *args, **kwargs)
    866 func = maybe_mangle_lambdas(func)
    868 op = GroupByApply(self, func, args, kwargs)
--> 869 result = op.agg()
    870 if not is_dict_like(func) and result is not None:
    871     return result

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/apply.py:168, in Apply.agg(self)
    165     return self.apply_str()
    167 if is_dict_like(arg):
--> 168     return self.agg_dict_like()
    169 elif is_list_like(arg):
    170     # we require a list, but not a 'str'
    171     return self.agg_list_like()

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/apply.py:498, in Apply.agg_dict_like(self)
    495         keys_to_use = ktu
    497     axis = 0 if isinstance(obj, ABCSeries) else 1
--> 498     result = concat(
    499         {k: results[k] for k in keys_to_use}, axis=axis, keys=keys_to_use
    500     )
    501 elif any(is_ndframe):
    502     # There is a mix of NDFrames and scalars
    503     raise ValueError(
    504         "cannot perform both aggregation "
    505         "and transformation operations "
    506         "simultaneously"
    507     )

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/util/_decorators.py:311, in deprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper(*args, **kwargs)
    305 if len(args) > num_allow_args:
    306     warnings.warn(
    307         msg.format(arguments=arguments),
    308         FutureWarning,
    309         stacklevel=stacklevel,
    310     )
--> 311 return func(*args, **kwargs)

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/reshape/concat.py:359, in concat(objs, axis, join, ignore_index, keys, levels, names, verify_integrity, sort, copy)
    155 """
    156 Concatenate pandas objects along a particular axis with optional set logic
    157 along the other axes.
   (...)
    344 ValueError: Indexes have overlapping values: ['a']
    345 """
    346 op = _Concatenator(
    347     objs,
    348     axis=axis,
   (...)
    356     sort=sort,
    357 )
--> 359 return op.get_result()

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/reshape/concat.py:599, in _Concatenator.get_result(self)
    596     new_data._consolidate_inplace()
    598 cons = sample._constructor
--> 599 return cons(new_data).__finalize__(self, method="concat")

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/geopandas/geodataframe.py:157, in GeoDataFrame.__init__(self, data, geometry, crs, *args, **kwargs)
    154 index = self.index
    155 try:
    156     if (
--> 157         hasattr(self["geometry"].values, "crs")
    158         and self["geometry"].values.crs
    159         and crs
    160         and not self["geometry"].values.crs == crs
    161     ):
    162         _crs_mismatch_warning()
    163         # TODO: raise error in 0.9 or 0.10.

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/geopandas/geodataframe.py:1327, in GeoDataFrame.__getitem__(self, key)
   1321 def __getitem__(self, key):
   1322     """
   1323     If the result is a column containing only 'geometry', return a
   1324     GeoSeries. If it's a DataFrame with a 'geometry' column, return a
   1325     GeoDataFrame.
   1326     """
-> 1327     result = super().__getitem__(key)
   1328     geo_col = self._geometry_column_name
   1329     if isinstance(result, Series) and isinstance(result.dtype, GeometryDtype):

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/frame.py:3473, in DataFrame.__getitem__(self, key)
   3471     if self.columns.is_unique and key in self.columns:
   3472         if isinstance(self.columns, MultiIndex):
-> 3473             return self._getitem_multilevel(key)
   3474         return self._get_item_cache(key)
   3476 # Do we have a slicer (on rows)?

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/frame.py:3560, in DataFrame._getitem_multilevel(self, key)
   3558 result_columns = maybe_droplevels(new_columns, key)
   3559 if self._is_mixed_type:
-> 3560     result = self.reindex(columns=new_columns)
   3561     result.columns = result_columns
   3562 else:

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/util/_decorators.py:324, in rewrite_axis_style_signature.<locals>.decorate.<locals>.wrapper(*args, **kwargs)
    322 @wraps(func)
    323 def wrapper(*args, **kwargs) -> Callable[..., Any]:
--> 324     return func(*args, **kwargs)

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/frame.py:4798, in DataFrame.reindex(self, *args, **kwargs)
   4796 kwargs.pop("axis", None)
   4797 kwargs.pop("labels", None)
-> 4798 return super().reindex(**kwargs)

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/generic.py:4974, in NDFrame.reindex(self, *args, **kwargs)
   4971     return self._reindex_multi(axes, copy, fill_value)
   4973 # perform the reindex on the axes
-> 4974 return self._reindex_axes(
   4975     axes, level, limit, tolerance, method, fill_value, copy
   4976 ).__finalize__(self, method="reindex")

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/frame.py:4611, in DataFrame._reindex_axes(self, axes, level, limit, tolerance, method, fill_value, copy)
   4609 columns = axes["columns"]
   4610 if columns is not None:
-> 4611     frame = frame._reindex_columns(
   4612         columns, method, copy, level, fill_value, limit, tolerance
   4613     )
   4615 index = axes["index"]
   4616 if index is not None:

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/frame.py:4656, in DataFrame._reindex_columns(self, new_columns, method, copy, level, fill_value, limit, tolerance)
   4643 def _reindex_columns(
   4644     self,
   4645     new_columns,
   (...)
   4651     tolerance=None,
   4652 ):
   4653     new_columns, indexer = self.columns.reindex(
   4654         new_columns, method=method, level=level, limit=limit, tolerance=tolerance
   4655     )
-> 4656     return self._reindex_with_indexers(
   4657         {1: [new_columns, indexer]},
   4658         copy=copy,
   4659         fill_value=fill_value,
   4660         allow_dups=False,
   4661     )

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/pandas/core/generic.py:5054, in NDFrame._reindex_with_indexers(self, reindexers, fill_value, copy, allow_dups)
   5051 if copy and new_data is self._mgr:
   5052     new_data = new_data.copy()
-> 5054 return self._constructor(new_data).__finalize__(self)

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/geopandas/geodataframe.py:164, in GeoDataFrame.__init__(self, data, geometry, crs, *args, **kwargs)
    162         _crs_mismatch_warning()
    163         # TODO: raise error in 0.9 or 0.10.
--> 164     self["geometry"] = _ensure_geometry(self["geometry"].values, crs)
    165 except TypeError:
    166     pass

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/geopandas/geodataframe.py:46, in _ensure_geometry(data, crs)
     44     return GeoSeries(out, index=data.index, name=data.name)
     45 else:
---> 46     out = from_shapely(data, crs=crs)
     47     return out

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/geopandas/array.py:151, in from_shapely(data, crs)
    135 def from_shapely(data, crs=None):
    136     """
    137     Convert a list or array of shapely objects to a GeometryArray.
    138 
   (...)
    149 
    150     """
--> 151     return GeometryArray(vectorized.from_shapely(data), crs=crs)

File ~/opt/anaconda3/envs/pyproj_env/lib/python3.9/site-packages/geopandas/array.py:280, in GeometryArray.__init__(self, data, crs)
    275     raise TypeError(
    276         "'data' should be array of geometry objects. Use from_shapely, "
    277         "from_wkb, from_wkt functions to construct a GeometryArray."
    278     )
    279 elif not data.ndim == 1:
--> 280     raise ValueError(
    281         "'data' should be a 1-dimensional array of geometry objects."
    282     )
    283 self.data = data
    285 self._crs = None

ValueError: 'data' should be a 1-dimensional array of geometry objects.
pandas: 1.4.1
geopandas: 0.10.2
osmnx: 1.1.2
  • 已将其更改为 MWE
  • 分离出了join()groupby()/agg()
  • 已包含版本
  • 我能看到一个区别 - python 3.9 对 3.10
import osmnx as ox
import geopandas as gpd
import pandas as pd
import io

df = pd.read_csv(
    io.StringIO(
        """AccidentUID,AccidentLocation_CHLV95_E,AccidentLocation_CHLV95_N
99BA5D383B96D02AE0430A865E33D02A,2663985,1213215
9B25C4871C909022E0430A865E339022,2666153,1211303
9B71AB601D948092E0430A865E338092,2666168,1211785
9C985CF7710A60C0E0430A865E3360C0,2663991,1213203
9EA9548660AB3002E0430A865E333002,2666231,1210786
9B2E8B25D5C29094E0430A865E339094,2666728,1210404
9C87C10FB73A905EE0430A865E33905E,2666220,1211811
9E30F39D35CA1058E0430A865E331058,2664599,1212960
9BC2EA43E0BFC068E0430A865E33C068,2665533,1212617
9C0BB9332AB30044E0430A865E330044,2666852,1211964"""
    )
)

gdf_loc = gpd.GeoDataFrame(
    data=df,
    geometry=gpd.points_from_xy(
        df["AccidentLocation_CHLV95_E"], df["AccidentLocation_CHLV95_N"]
    ),
    crs="EPSG:2056",
).to_crs("epsg:4326")

# get OSM data for investigated location
G = ox.graph_from_place("Luzern, Switzerland", network_type="drive")
G_proj = ox.project_graph(G)
gdf_nodes, gdf_edges = ox.utils_graph.graph_to_gdfs(G_proj)

# project graph and points
gdf_loc_p = gdf_loc["geometry"].to_crs(G_proj.graph["crs"])

ne, d = ox.nearest_edges(
    G_proj, X=gdf_loc_p.x.values, Y=gdf_loc_p.y.values, return_dist=True
)

# reindex points based on results from nearest_edges
gdf_loc = (
    gdf_loc.set_index(pd.MultiIndex.from_tuples(ne, names=["u", "v", "key"]))
    .assign(distance=d)
    .sort_index()
)

# join geometry from edges back to points
gdf_bad_roads = gdf_edges.join(gdf_loc, rsuffix="_loc", how="inner")
# aggregate so have number of accidents on each edge
gdf_bad_roads_agg = gdf_bad_roads.groupby(["u", "v", "key"]).agg(
    geometry=("geometry", "first"), number=("osmid", "size")
).set_crs(gdf_edges.crs)

print(f"""
pandas: {pd.__version__}
geopandas: {gpd.__version__}
osmnx: {ox.__version__}""")
pandas: 1.4.0
geopandas: 0.10.2
osmnx: 1.1.2

替代聚合语法。已确认两项工作

  • 因此结论是 named aggregations 失败了。可能应该在 pandas 上作为问题提出,但并非在所有环境
  • 上都失败
  • groupby()/apply() 正在对共享边执行 first 并且还需要再次设置 CRS
  • dissolve() 正在对几何体进行 一元联合 。概念上应该是相同的,但给出的几何形状略有不同。 (相同几何形状的一元并集恕我直言是其中一个几何形状的实例)
gdf_bad_roads.groupby(["u", "v", "key"]).agg({"geometry":"first", "AccidentUID":"size"}).set_crs(gdf_edges.crs).explore(color="blue")


gdf_bad_roads.dissolve(["u", "v", "key"], aggfunc={"AccidentUID":"size"}).explore(color="blue")