Geopandas读取自制GeoJSON文件失败问题求助
GeoJSON读取失败:DataSourceError 排查与解决
问题重现
执行以下代码导出并读取GeoJSON时触发DataSourceError:
import geopandas as gpd # 读取shp文件 vec_data = gpd.read_file("map.shp") vec_data.head() vec_data['LPIS_name'].unique() # 筛选永久草地并导出为GeoJSON sel_crop = vec_data[vec_data.LPIS_name == 'Permanent Grassland'] sel_crop.to_file("Permanent_Grassland.geojson", driver='GeoJSON') # 读取生成的GeoJSON时出错 feature = gpd.read_file("Permanent_Grassland.geojson")
完整错误信息
--------------------------------------------------------------------------- DataSourceError Traceback (most recent call last) Cell In[8], line 1 ----> 1 feature = gpd.read_file(path_feature) File c:\\Users\\bventura\\AppData\\Local\\anaconda3\\Lib\\site-packages\\geopandas\\io\\file.py:294, in _read_file(filename, bbox, mask, columns, rows, engine, **kwargs) 291 from_bytes = True 293 if engine == "pyogrio": ---> 294 return _read_file_pyogrio( 295 filename, bbox=bbox, mask=mask, columns=columns, rows=rows, **kwargs 296 ) 298 elif engine == "fiona": 299 if pd.api.types.is_file_like(filename): File c:\\Users\\bventura\\AppData\\Local\\anaconda3\\Lib\\site-packages\\geopandas\\io\\file.py:547, in _read_file_pyogrio(path_or_bytes, bbox, mask, rows, **kwargs) 538 warnings.warn( 539 "The 'include_fields' and 'ignore_fields' keywords are deprecated, and " 540 "will be removed in a future release. You can use the 'columns' keyword " (...) 543 stacklevel=3, 544 ) 545 kwargs["columns"] = kwargs.pop("include_fields") ---> 547 return pyogrio.read_dataframe(path_or_bytes, bbox=bbox, **kwargs) File c:\\Users\\bventura\\AppData\\Local\\anaconda3\\Lib\\site-packages\\pyogrio\\geopandas.py:261, in read_dataframe(path_or_buffer, layer, encoding, columns, read_geometry, force_2d, skip_features, max_features, where, bbox, mask, fids, sql, sql_dialect, fid_as_index, use_arrow, on_invalid, arrow_to_pandas_kwargs, **kwargs) 256 if not use_arrow: 257 # For arrow, datetimes are read as is. 258 # For numpy IO, datetimes are read as string values to preserve timezone info 259 # as numpy does not directly support timezones. 260 kwargs["datetime_as_string"] = True ---> 261 result = read_func( 262 path_or_buffer, 263 layer=layer, 264 encoding=encoding, 265 columns=columns, 266 read_geometry=read_geometry, 267 force_2d=gdal_force_2d, 268 skip_features=skip_features, 269 max_features=max_features, 270 where=where, 271 bbox=bbox, 272 mask=mask, 273 fids=fids, 274 sql=sql, 275 sql_dialect=sql_dialect, 276 return_fids=fid_as_index, 277 **kwargs, 278 ) 280 if use_arrow: 281 meta, table = result File c:\\Users\\bventura\\AppData\\Local\\anaconda3\\Lib\\site-packages\\pyogrio\\raw.py:196, in read(path_or_buffer, layer, encoding, columns, read_geometry, force_2d, skip_features, max_features, where, bbox, mask, fids, sql, sql_dialect, return_fids, datetime_as_string, **kwargs) 56 """Read OGR data source into numpy arrays. 57 58 IMPORTANT: non-linear geometry types (e.g., MultiSurface) are converted (...) 191 192 """ 194 dataset_kwargs = _preprocess_options_key_value(kwargs) if kwargs else {} ---> 196 return ogr_read( 197 get_vsi_path_or_buffer(path_or_buffer), 198 layer=layer, 199 encoding=encoding, 200 columns=columns, 201 read_geometry=read_geometry, 202 force_2d=force_2d, 203 skip_features=skip_features, 204 max_features=max_features or 0, 205 where=where, 206 bbox=bbox, 207 mask=_mask_to_wkb(mask), 208 fids=fids, 209 sql=sql, 210 sql_dialect=sql_dialect, 211 return_fids=return_fids, 212 dataset_kwargs=dataset_kwargs, 213 datetime_as_string=datetime_as_string, 214 ) File c:\\Users\\bventura\\AppData\\Local\\anaconda3\\Lib\\site-packages\\pyogrio\\_io.pyx:1239, in pyogrio._io.ogr_read() File c:\\Users\\bventura\\AppData\\Local\\anaconda3\\Lib\\site-packages\\pyogrio\\_io.pyx:219, in pyogrio._io.ogr_open() DataSourceError: Failed to read GeoJSON data
怀疑原因
问题大概率出在Polygon和MultiPolygon未遵循右手定则——OGR/GeoJSON规范要求多边形顶点按右手定则排列(外环逆时针,内环顺时针),不符合该规则的几何会导致读取失败。
解决方案
方案1:修复几何顶点顺序(推荐)
导出GeoJSON前,通过shapely的orient函数统一调整顶点顺序,使其符合右手定则:
import geopandas as gpd from shapely.geometry.polygon import orient # 读取shp文件 vec_data = gpd.read_file("map.shp") # 筛选目标数据 sel_crop = vec_data[vec_data.LPIS_name == 'Permanent Grassland'] # 修复几何顶点顺序,sign=1.0表示外环逆时针 sel_crop['geometry'] = sel_crop['geometry'].apply(lambda geom: orient(geom, sign=1.0)) # 导出为GeoJSON sel_crop.to_file("Permanent_Grassland.geojson", driver='GeoJSON') # 验证读取 feature = gpd.read_file("Permanent_Grassland.geojson") feature.head()
方案2:跳过无效几何(临时应急)
若无需修复几何,可在读取时指定on_invalid='skip'参数跳过无效条目,但这会丢失部分数据,仅作为临时方案:
feature = gpd.read_file("Permanent_Grassland.geojson", on_invalid='skip')
内容的提问来源于stack exchange,提问作者sylar_80
相关产品推荐
相关产品推荐

