mirror of
https://github.com/wassname/geopandas.git
synced 2026-09-09 11:22:50 +08:00
ENH: Add where filter to read_file (#2552)
This commit is contained in:
@@ -6,6 +6,8 @@ Development version
|
||||
|
||||
New features and improvements:
|
||||
|
||||
- Add where filter to ``read_file`` (#2552)
|
||||
|
||||
Deprecations and compatibility notes:
|
||||
|
||||
Bug fixes:
|
||||
|
||||
@@ -177,6 +177,23 @@ Skip loading geometry from the file:
|
||||
)
|
||||
|
||||
|
||||
SQL WHERE Filter
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Load in a subset of data with a `SQL WHERE clause <https://gdal.org/user/ogr_sql_dialect.html#where>`__.
|
||||
|
||||
.. note:: Requires Fiona 1.9+ or the pyogrio engine.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
gdf = geopandas.read_file(
|
||||
geopandas.datasets.get_path("naturalearth_lowres"),
|
||||
where="continent='Africa'",
|
||||
)
|
||||
|
||||
|
||||
Writing Spatial Data
|
||||
---------------------
|
||||
|
||||
|
||||
+21
-6
@@ -26,12 +26,14 @@ _VALID_URLS.discard("")
|
||||
fiona = None
|
||||
fiona_env = None
|
||||
fiona_import_error = None
|
||||
FIONA_GE_19 = False
|
||||
|
||||
|
||||
def _import_fiona():
|
||||
global fiona
|
||||
global fiona_env
|
||||
global fiona_import_error
|
||||
global FIONA_GE_19
|
||||
|
||||
if fiona is None:
|
||||
try:
|
||||
@@ -48,6 +50,9 @@ def _import_fiona():
|
||||
except ImportError:
|
||||
fiona_env = None
|
||||
|
||||
FIONA_GE_19 = Version(Version(fiona.__version__).base_version) >= Version(
|
||||
"1.9.0"
|
||||
)
|
||||
except ImportError as err:
|
||||
fiona = False
|
||||
fiona_import_error = str(err)
|
||||
@@ -263,8 +268,11 @@ def _read_file(filename, bbox=None, mask=None, rows=None, engine=None, **kwargs)
|
||||
|
||||
|
||||
def _read_file_fiona(
|
||||
path_or_bytes, from_bytes, bbox=None, mask=None, rows=None, **kwargs
|
||||
path_or_bytes, from_bytes, bbox=None, mask=None, rows=None, where=None, **kwargs
|
||||
):
|
||||
if where is not None and not FIONA_GE_19:
|
||||
raise NotImplementedError("where requires fiona 1.9+")
|
||||
|
||||
if not from_bytes:
|
||||
# Opening a file via URL or file-like-object above automatically detects a
|
||||
# zipped file. In order to match that behavior, attempt to add a zip scheme
|
||||
@@ -319,17 +327,24 @@ def _read_file_fiona(
|
||||
mask = mapping(mask.to_crs(crs).unary_union)
|
||||
elif isinstance(mask, BaseGeometry):
|
||||
mask = mapping(mask)
|
||||
|
||||
filters = {}
|
||||
if bbox is not None:
|
||||
filters["bbox"] = bbox
|
||||
if mask is not None:
|
||||
filters["mask"] = mask
|
||||
if where is not None:
|
||||
filters["where"] = where
|
||||
|
||||
# setup the data loading filter
|
||||
if rows is not None:
|
||||
if isinstance(rows, int):
|
||||
rows = slice(rows)
|
||||
elif not isinstance(rows, slice):
|
||||
raise TypeError("'rows' must be an integer or a slice.")
|
||||
f_filt = features.filter(
|
||||
rows.start, rows.stop, rows.step, bbox=bbox, mask=mask
|
||||
)
|
||||
elif any((bbox, mask)):
|
||||
f_filt = features.filter(bbox=bbox, mask=mask)
|
||||
f_filt = features.filter(rows.start, rows.stop, rows.step, **filters)
|
||||
elif filters:
|
||||
f_filt = features.filter(**filters)
|
||||
else:
|
||||
f_filt = features
|
||||
# get list of columns
|
||||
|
||||
@@ -37,10 +37,12 @@ try:
|
||||
FIONA_GE_1814 = Version(fiona.__version__) >= Version("1.8.14")
|
||||
# invalid datetime handling
|
||||
FIONA_GE_1821 = Version(fiona.__version__) >= Version("1.8.21")
|
||||
FIONA_GE_19 = Version(Version(fiona.__version__).base_version) >= Version("1.9.0")
|
||||
except ImportError:
|
||||
fiona = False
|
||||
FIONA_GE_1814 = False
|
||||
FIONA_GE_1821 = False
|
||||
FIONA_GE_19 = False
|
||||
|
||||
|
||||
PYOGRIO_MARK = pytest.mark.skipif(not pyogrio, reason="pyogrio not installed")
|
||||
@@ -766,6 +768,23 @@ def test_read_file__ignore_all_fields(engine):
|
||||
assert gdf.columns.tolist() == ["geometry"]
|
||||
|
||||
|
||||
def test_read_file__where_filter(engine):
|
||||
if FIONA_GE_19 or engine == "pyogrio":
|
||||
gdf = geopandas.read_file(
|
||||
geopandas.datasets.get_path("naturalearth_lowres"),
|
||||
where="continent='Africa'",
|
||||
engine=engine,
|
||||
)
|
||||
assert gdf.continent.unique().tolist() == ["Africa"]
|
||||
else:
|
||||
with pytest.raises(NotImplementedError):
|
||||
geopandas.read_file(
|
||||
geopandas.datasets.get_path("naturalearth_lowres"),
|
||||
where="continent='Africa'",
|
||||
engine="fiona",
|
||||
)
|
||||
|
||||
|
||||
@PYOGRIO_MARK
|
||||
def test_read_file__columns():
|
||||
# TODO: this is only support for pyogrio, but we could mimic it for fiona as well
|
||||
|
||||
Reference in New Issue
Block a user