Open-source project
geopandas/dask-geopandas avatar
geopandas/dask-geopandas

dask-geopandas: running GeoPandas operations on Dask

Parallel GeoPandas with Dask

593 stars51 forksPythonBSD-3-Clause

At a glance

What is it?
dask-geopandas is a bridge between GeoPandas and Dask, so a GeoDataFrame can be repartitioned into a Dask-backed frame and its spatial methods computed in parallel. The package is a small layer over two mature projects rather than a parallel implementation, and its constraints follow from that.
Who is it for?
Adopt dask-geopandas if your geospatial workload is a single large frame that Dask's partitioning can split usefully, and you are already on GeoPandas 1.0 and Shapely 2.1 so the geometry assumptions line up. Do not adopt it if your data is small enough to fit in memory, or if you need clustering guarantees the Dask DataFrame backend does not provide.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 95 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A bridge, not a parallel geospatial stack

The README describes the project as one that merges the geospatial capabilities of GeoPandas with the scalability of Dask, and then is unusually precise about what that means. GeoPandas extends the datatypes used by pandas to allow spatial operations on geometric types, and Dask provides advanced parallelism and distributed out-of-core computation with a dask.dataframe module designed to scale pandas. Since GeoPandas is an extension to the pandas DataFrame, the same way Dask scales pandas can also be applied to GeoPandas.

That reasoning is the whole architecture. The project is described as a bridge between Dask and GeoPandas that offers geospatial capabilities of GeoPandas backed by Dask. There is no new geometry engine, no new spatial index, and no second implementation of the spatial predicates. What you get is the GeoPandas API running on a partitioned frame.

The practical consequence is that the partitioning strategy is inherited from the Dask DataFrame, and the spatial operations are inherited from GeoPandas. A spatial join that a GeoPandas user would expect to be a single indexed operation has to work across partitions, and that is where the practical difficulty of this kind of library usually lives.

The repository confirms the bridging nature. There is a `dask_geopandas/` package directory, a `setup.py` that exists mostly to wire up versioneer, a `versioneer.py`, and a `CHANGELOG.md`. The classifier says `Development Status :: 5 - Production/Stable`, the licence is BSD 3-Clause, and the maintainers are listed as the GeoPandas contributors rather than an individual, which is the arrangement you would expect from a package hosted inside the GeoPandas organization.

Repartitioning is the entry point to parallel spatial work

The Example section is short, and it shows the whole API surface you need to start.

You begin with an ordinary GeoPandas dataframe:

python
   import geopandas
   df = geopandas.read_file('...')

And you repartition it into a Dask-GeoPandas dataframe with a partition count:

python
   import dask_geopandas
   ddf = dask_geopandas.from_geopandas(df, npartitions=4)

The `npartitions` argument is the first real decision. Dask's partitioning does not know anything about spatial locality, so `from_geopandas` splits the existing frame by row order, and the quality of that split determines whether a spatial operation can be done partition-locally. A frame sorted by identifier splits into spatially scattered chunks, and a spatial join between partitions then has to bring data together.

After that, the familiar spatial attributes and methods of GeoPandas are also available and will be computed in parallel:

python
   ddf.geometry.area.compute()
   ddf.within(polygon)

The two examples show the two halves of the deferred model. `ddf.geometry.area.compute()` triggers the computation and returns a concrete result, while `ddf.within(polygon)` stays lazy and returns a Dask object you can keep filtering on. The `.geometry` accessor is where the GeoPandas behavior lives, and `.compute()` is where Dask's laziness ends.

One point worth flagging: the example uses a plain GeoPandas frame as the source rather than a file read directly by Dask. That is a deliberate choice in the documentation, and it has a consequence. If you read a large dataset with `geopandas.read_file` first, you have already paid to load it all into one process, and the partitioning happens afterward. For a dataset that genuinely does not fit in memory, that ordering defeats the purpose, and the source of the partition has to be the Dask side rather than a single in-memory frame.

The dependency floors are what decide whether it installs

The `pyproject.toml` states the runtime requirements, and they are strict enough to shape your environment planning.

The declared dependencies are `geopandas>=1.0.0`, `shapely>=2.1` and `dask[dataframe]>=2025.1.0`, with `requires-python` of 3.11 or newer. The optional test extra is just `pytest`.

The Shapely floor is the one to notice. Shapely 2.0 was the release that moved to a new array interface and reorganized the geometry objects, and requiring 2.1 means the package is written against that generation of the API rather than the 1.x series. If your environment is pinned to Shapely 1.8, this package will not install, and that is a deliberate line rather than an oversight.

The GeoPandas floor of 1.0.0 matters for the same reason. GeoPandas 1.0 is a relatively recent major release, and the fact that the dependency starts there tells you this package targets the current generation of the GeoPandas API rather than maintaining compatibility with the long tail of older versions.

The Dask floor is expressed as a calendar-style version, `>=2025.1.0`, which is Dask's date-based release scheme rather than a semantic version. The `dataframe` extra is requested explicitly, which is right, since the Dask DataFrame backend is where all the partitioning logic lives.

The build itself is ordinary. The build backend is `setuptools.build_meta` with `setuptools>=42` and `wheel` required, and the version is dynamic. The `setup.py` is a thin shim whose only job is to make versioneer work, and it explains why in a comment about the current directory needing to be on `sys.path` so that versioneer can be imported when pip uses PEP 517 and 518 build rules.

Conda is the documented install path, with a strict channel setup

The Installation section gives one method rather than a choice, and the channel configuration in it is the part people usually skip.

The package depends on Shapely, GeoPandas and Dask, and the README presents conda as the way to install all required dependencies. The sequence is four commands, and two of them configure the environment rather than install anything:

bash
    conda create -n geo_env
    conda activate geo_env
    conda config --env --add channels conda-forge
    conda config --env --set channel_priority strict
    conda install dask-geopandas

Setting channel priority to strict is the significant instruction. The `conda-forge` channel is added to the environment, and strict priority means packages from it are preferred over the defaults, which is how you get a consistent Shapely and GeoPandas build rather than a mix. The `--env` flag means the change applies to this environment only, so it does not alter the user's global conda configuration.

The README does not give a pip command, though the package is on PyPI and the badges point at both the PyPI project and the conda-forge channel. Since the dependencies are the same either way, the practical difference is that pip will resolve `geopandas`, `shapely` and `dask` without the conda-forge pins that the strict priority setting gives you, and binary wheels for Shapely and GDAL are the part of the install most likely to differ.

The documentation itself lives at dask-geopandas.readthedocs.io, and the README points at it for anything beyond the quick example.

The geopandas organization and the tooling tell you how it is maintained

The repository sits under the `geopandas` organization rather than a personal account, and the maintainers field in the project metadata reads `GeoPandas contributors`. The homepage link in the metadata points to geopandas.org rather than a personal site, and the issue tracker is the organization's.

That arrangement has a practical meaning for an adopter. The package is versioned by the people who maintain GeoPandas, so a breaking change in GeoPandas is likely to be reflected here, and the release history is visible. The listed releases are v0.5.0 on 2025-06-02, v0.4.3 on 2025-01-19 and v0.4.2 on 2024-09-24, which shows a steady release cadence for a package whose surface is small.

The last push was on 2026-07-21 and the repository is not archived.

The development tooling is modern and worth mentioning for anyone who wants to contribute. There is a `pyproject.toml` with a `tool.black` section setting line-length to 88, and a `tool.ruff` section with the same line-length, an exclude list covering `doc/*`, `versioneer.py` and `dask_geopandas/_version.py`, and a lint selection that enables pyflakes, pycodestyle, flake8-bugbear, flake8-debugger, pylint rules, PIE and isort. The presence of both Black and Ruff is the current convention for a project that wants formatting and linting to agree with each other.

There is a `.pre-commit-config.yaml`, a `.coveragerc`, a `ci/` directory, `requirements-dev.txt` for the development extras, and a `readthedocs.yml` for the documentation build. The `MANIFEST.in` handles what goes into the source distribution, and `CONTRIBUTING.md` is present at the root, so the contribution path is documented rather than implied.

Compared with plain GeoPandas and with a different parallel engine

Two alternatives frame the decision, and the differences in approach are clearer than the feature lists.

Plain GeoPandas is the baseline. It is a single-process library with an index on the geometry, and for a dataset that fits in memory it is the right tool, because every spatial operation is a local indexed lookup. dask-geopandas only earns its place when the data does not fit, or when a single machine's cores are the limit. The overhead it adds is real: a GeoDataFrame becomes a Dask collection, operations become lazy, and results have to be computed. If you are calling `.compute()` on every operation in a loop, the partitioning bought you nothing.

The second alternative is a different parallel engine, where the partitioning and the parallelism live in a system built around distributed arrays or a database rather than the Dask DataFrame. The difference in approach is that those systems push computation to workers and keep the data in a store, while Dask's DataFrame model is a lazy dataframe over partitions that can be scheduled on a cluster or run locally with a threaded or process scheduler. A distributed array system will chunk along an index and require the geometry to be encoded in arrays. Dask-GeoPandas keeps the GeoPandas object model intact and partitions the rows.

The practical consequence is where the chunk boundaries fall. For a dataset indexed by something geographically meaningful, a system that chunks by that index keeps spatial queries local. Dask-GeoPandas partitions by row order, so the caller has to think about whether the source ordering is spatially meaningful, and if it is not, reorder before converting.

Editorial conclusion

Adopt dask-geopandas if your geospatial workload is a single large frame that Dask's partitioning can split usefully, and you are already on GeoPandas 1.0 and Shapely 2.1 so the geometry assumptions line up. Do not adopt it if your data is small enough to fit in memory, or if you need clustering guarantees the Dask DataFrame backend does not provide. Verify first that your geopandas and shapely versions satisfy the declared floors, since the package pins geopandas>=1.0.0 and shapely>=2.1, and that your spatial joins distribute rather than requiring all data on one worker.

Frequently asked questions

What is dask-geopandas and what problem does it solve?

It is a bridge between Dask and GeoPandas that offers the geospatial capabilities of GeoPandas backed by Dask. The README explains that since GeoPandas extends the pandas DataFrame, the same way Dask scales pandas can also be applied to GeoPandas.

How do I install dask-geopandas?

The README documents conda as the way to install all required dependencies: create an environment, activate it, add conda-forge as a channel with strict channel priority, then run `conda install dask-geopandas`. The package is also published on PyPI, and it requires Python 3.11 or newer.

How do I convert a GeoDataFrame into a parallel dask-geopandas frame?

Use `dask_geopandas.from_geopandas(df, npartitions=4)` on an existing GeoPandas frame. The README notes that the familiar spatial attributes and methods of GeoPandas are then available and computed in parallel, for example `ddf.geometry.area.compute()` and `ddf.within(polygon)`.

Which versions of geopandas, shapely and dask does dask-geopandas need?

The pyproject.toml declares `geopandas>=1.0.0`, `shapely>=2.1` and `dask[dataframe]>=2025.1.0`, with `requires-python` set to 3.11 or newer. The Shapely 2.1 floor in particular rules out the 1.x series.

What license is dask-geopandas released under?

BSD 3-Clause, according to the project metadata and the LICENSE file at the repository root. The project is maintained by the GeoPandas contributors under the geopandas GitHub organization, and the last push was on 2026-07-21.

Official sources

  1. geopandas/dask-geopandas on GitHub
  2. License: BSD-3-Clause
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/geopandas-dask-geopandas.svg)](https://hysenlabs.com/projects/geopandas-dask-geopandas)

Was this useful?