Merge remote-tracking branch 'upstream/main' into pr/wassname/416-2

This commit is contained in:
Martin Fleischmann
2022-02-20 15:08:31 +00:00
199 changed files with 22815 additions and 8606 deletions
+39
View File
@@ -0,0 +1,39 @@
---
name: Bug Report
about: Create a bug report to help us improve geopandas
title: "BUG:"
labels: "bug, needs triage"
---
- [ ] I have checked that this issue has not already been reported.
- [ ] I have confirmed this bug exists on the latest version of geopandas.
- [ ] (optional) I have confirmed this bug exists on the main branch of geopandas.
---
**Note**: Please read [this guide](https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports) detailing how to provide the necessary information for us to reproduce your bug.
#### Code Sample, a copy-pastable example
```python
# Your code here
```
#### Problem description
[this should explain **why** the current behaviour is a problem and why the expected output is a better solution]
#### Expected Output
#### Output of ``geopandas.show_versions()``
<details>
[paste the output of ``geopandas.show_versions()`` here leaving a blank line after the details tag]
</details>
+34
View File
@@ -0,0 +1,34 @@
---
name: Feature Request
about: Suggest an idea for geopandas
title: "ENH:"
labels: "enhancement"
---
#### Is your feature request related to a problem?
[this should provide a description of what the problem is, e.g. "I wish I could use geopandas to do [...]"]
#### Describe the solution you'd like
[this should provide a description of the feature request, e.g. "`GeoDataFrame.foo` should get a new parameter `bar` that [...]", try to write a docstring for the desired feature]
#### API breaking implications
[this should provide a description of how this feature will affect the API]
#### Describe alternatives you've considered
[this should provide a description of any alternative solutions or features you've considered]
#### Additional context
[add any other context, code examples, or references to existing implementations about the feature request here]
```python
# Your code here, if applicable
```
@@ -0,0 +1,31 @@
---
name: Installation Issue
about: Ask about installing geopandas
title: ""
labels: "installation"
---
- [ ] I have read the [documentation on installation](https://geopandas.org/install.html) and followed the instructions provided.
- [ ] I have looked through [issues labeled "installation"](https://github.com/geopandas/geopandas/labels/installation) in the geopandas repo.
- If your issue is related to installation using the `conda-forge` channel, please open an issue in [geopandas-feedstock repository](https://github.com/conda-forge/geopandas-feedstock) instead.
---
#### System information
[what operating system do you have and what package management system are you
using]
#### Environment details
<details>
[if using conda, paste the output of `conda info` and `conda list`; if using
pip, `pip freeze`]
</details>
+24
View File
@@ -0,0 +1,24 @@
---
name: Submit Question
about: Ask a general question about geopandas
title: "QST:"
labels: "question"
---
- [ ] I have searched the [geopandas] tag on [StackOverflow](https://stackoverflow.com/questions/tagged/geopandas) and [GIS StackExchange](https://gis.stackexchange.com/questions/tagged/geopandas) for similar questions.
- [ ] I have asked my usage related question on [StackOverflow](https://stackoverflow.com) or [GIS StackExhange](https://gis.stackexchange.com).
---
#### Question about geopandas
**Note**: If you'd still like to submit a question, please read [this guide](
https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports) detailing how to provide the necessary information for us to reproduce your question.
```python
# Your code here, if applicable
```
+60
View File
@@ -0,0 +1,60 @@
name: Publish geopandas to PyPI / GitHub
on:
push:
tags:
- "v*"
jobs:
build-n-publish:
name: Build and publish geopandas to PyPI
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.x"
- name: Build a binary wheel and a source tarball
run: |
python -m pip install --upgrade pip
pip install setuptools wheel
python setup.py sdist bdist_wheel
- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
- name: Create GitHub Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
draft: false
prerelease: false
- name: Get Asset name
run: |
export PKG=$(ls dist/ | grep tar)
set -- $PKG
echo "name=$1" >> $GITHUB_ENV
- name: Upload Release Asset (sdist) to GitHub
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: dist/${{ env.name }}
asset_name: ${{ env.name }}
asset_content_type: application/zip
+127
View File
@@ -0,0 +1,127 @@
name: Tests
on:
push:
branches: [main, 0.**]
pull_request:
branches: [main, 0.**]
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
Linting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: pre-commit/action@v2.0.3
Test:
needs: Linting
name: ${{ matrix.os }}, ${{ matrix.env }}
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash -l {0}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
postgis: [false]
dev: [false]
env:
- ci/envs/37-minimal.yaml
- ci/envs/38-no-optional-deps.yaml
- ci/envs/37-pd10.yaml
- ci/envs/37-latest-defaults.yaml
- ci/envs/37-latest-conda-forge.yaml
- ci/envs/38-latest-conda-forge.yaml
- ci/envs/39-latest-conda-forge.yaml
- ci/envs/310-latest-conda-forge.yaml
include:
- env: ci/envs/37-latest-conda-forge.yaml
os: macos-latest
postgis: false
dev: false
- env: ci/envs/38-latest-conda-forge.yaml
os: macos-latest
postgis: false
dev: false
- env: ci/envs/37-latest-conda-forge.yaml
os: windows-latest
postgis: false
dev: false
- env: ci/envs/38-latest-conda-forge.yaml
os: windows-latest
postgis: false
dev: false
- env: ci/envs/310-dev.yaml
os: ubuntu-latest
dev: true
steps:
- uses: actions/checkout@v2
- name: Setup Conda
uses: conda-incubator/setup-miniconda@v2
with:
environment-file: ${{ matrix.env }}
miniforge-version: latest
miniforge-variant: Mambaforge
use-mamba: true
- name: Check and Log Environment
run: |
python -V
python -c "import geopandas; geopandas.show_versions();"
conda info
# save conda list to file and print out
# so that we can do the HAS_PYGEOS check without calling conda again
conda list 2>&1 | tee conda.txt
if ( cat conda.txt | grep -q pygeos )
then
echo "Setting HAS_PYGEOS=1"
echo "HAS_PYGEOS=1" >> $GITHUB_ENV
else
echo "Setting HAS_PYGEOS=0"
echo "HAS_PYGEOS=0" >> $GITHUB_ENV
fi
- name: Test without PyGEOS
env:
USE_PYGEOS: 0
run: |
pytest -v -r s -n auto --color=yes --cov=geopandas --cov-append --cov-report term-missing --cov-report xml geopandas/
- name: Test with PyGEOS
if: env.HAS_PYGEOS == 1
env:
USE_PYGEOS: 1
run: |
pytest -v -r s -n auto --color=yes --cov=geopandas --cov-append --cov-report term-missing --cov-report xml geopandas/
- name: Test with PostGIS
if: contains(matrix.env, '38-latest-conda-forge.yaml') && contains(matrix.os, 'ubuntu')
env:
PGUSER: postgres
PGPASSWORD: postgres
PGHOST: "127.0.0.1"
PGPORT: 5432
run: |
conda install postgis -c conda-forge
sh ci/scripts/setup_postgres.sh
pytest -v -r s --color=yes --cov=geopandas --cov-append --cov-report term-missing --cov-report xml geopandas/io/tests/test_sql.py | tee /dev/stderr | if grep SKIPPED >/dev/null;then echo "TESTS SKIPPED, FAILING" && exit 1;fi
- name: Test docstrings
if: contains(matrix.env, '38-latest-conda-forge.yaml') && contains(matrix.os, 'ubuntu')
env:
USE_PYGEOS: 1
run: |
pytest -v --color=yes --doctest-only geopandas --ignore=geopandas/datasets
- uses: codecov/codecov-action@v2
+3 -1
View File
@@ -34,6 +34,7 @@ nosetests.xml
coverage.xml
*.cover
.hypothesis/
result_images
# Sphinx documentation
doc/_build/
@@ -59,11 +60,12 @@ doc/_build/
examples/nybb_*.zip
doc/source/gallery
doc/source/savefig
doc/source/reference
doc/source/docs/reference/api/*.rst
geopandas.egg-info
geopandas/version.py
.asv
doc/source/getting_started/my_file.geojson
+4 -3
View File
@@ -1,11 +1,12 @@
files: 'geopandas\/'
repos:
- repo: https://github.com/python/black
rev: stable
rev: 20.8b1
hooks:
- id: black
language_version: python3.7
language_version: python3
- repo: https://gitlab.com/pycqa/flake8
rev: 3.7.7
rev: 3.8.3
hooks:
- id: flake8
language: python_venv
-69
View File
@@ -1,69 +0,0 @@
language: python
sudo: false
matrix:
include:
# One build with minimum versions of dependencies
- env: ENV_FILE="ci/travis/35-minimal.yaml"
# one build with no optional dependencies
- env: ENV_FILE="ci/travis/38-no-optional-deps.yaml"
# Python 3.6 test all supported Pandas versions
- env: ENV_FILE="ci/travis/36-pd023.yaml" PYGEOS=true
- env: ENV_FILE="ci/travis/36-pd024.yaml" PYGEOS=true
- env: ENV_FILE="ci/travis/37-latest-defaults.yaml" STYLE=true PYGEOS=true
- env: ENV_FILE="ci/travis/37-latest-conda-forge.yaml" PYGEOS=true
- env: ENV_FILE="ci/travis/38-latest-conda-forge.yaml" PYGEOS=true POSTGIS=true PGUSER=postgres PGPASSWORD=postgres
- env: ENV_FILE="ci/travis/37-dev.yaml" DEV=true PYGEOS=true
allow_failures:
- env: ENV_FILE="ci/travis/37-dev.yaml" DEV=true PYGEOS=true
before_install:
- chmod +x ci/travis/setup_postgres.sh
install:
# Install conda
- wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
- bash miniconda.sh -b -p $HOME/miniconda
- export PATH="$HOME/miniconda/bin:$PATH"
- conda config --set always_yes yes --set changeps1 no
- conda update conda
- conda info
# free channel needed for older envs (< py37), see
# https://github.com/conda/conda/issues/8849
- conda config --set restore_free_channel true
# Install dependencies
- conda env create --file="${ENV_FILE}"
- source activate test
- if [ "$DEV" ]; then pip install git+https://github.com/pydata/pandas.git; fi
- if [ "$DEV" ]; then pip install git+https://github.com/matplotlib/matplotlib.git; fi
- if [ "$DEV" ]; then pip install git+https://github.com/Toblerity/Shapely.git; fi
- if [ "$STYLE" ]; then pip install black flake8; fi
- if [ "$POSTGIS" ]; then conda install postgis -c conda-forge; fi
- pip install -e .
# List environment
- conda list
- python -c "import geopandas; geopandas.show_versions();"
# Set-up database
- if [ "$POSTGIS" ]; then ci/travis/setup_postgres.sh; fi
script:
- echo "Testing without PyGEOS"
- USE_PYGEOS=0 pytest geopandas -v -r s --cov geopandas --cov-report term-missing
- if [ "$PYGEOS" ]; then echo "Testing with PyGEOS"; fi
- if [ "$PYGEOS" ]; then USE_PYGEOS=1 pytest geopandas -v -r s --cov-append --cov geopandas --cov-report term-missing; fi
- if [ "$STYLE" ]; then black --check geopandas; fi
- if [ "$STYLE" ]; then flake8 geopandas; fi
after_success:
- codecov
+359 -2
View File
@@ -1,6 +1,356 @@
Changelog
=========
Version 0.10.2 (October 16, 2021)
---------------------------------
Small bug-fix release:
- Fix regression in `overlay()` in case no geometries are intersecting (but
have overlapping total bounds) (#2172).
- Fix regression in `overlay()` with `keep_geom_type=True` in case the
overlay of two geometries in a GeometryCollection with other geometry types
(#2177).
- Fix `overlay()` to honor the `keep_geom_type` keyword for the
`op="differnce"` case (#2164).
- Fix regression in `plot()` with a mapclassify `scheme` in case the
formatted legend labels have duplicates (#2166).
- Fix a bug in the `explore()` method ignoring the `vmin` and `vmax` keywords
in case they are set to 0 (#2175).
- Fix `unary_union` to correctly handle a GeoSeries with missing values (#2181).
- Avoid internal deprecation warning in `clip()` (#2179).
Version 0.10.1 (October 8, 2021)
--------------------------------
Small bug-fix release:
- Fix regression in `overlay()` with non-overlapping geometries and a
non-default `how` (i.e. not "intersection") (#2157).
Version 0.10.0 (October 3, 2021)
--------------------------------
Highlights of this release:
- A new `sjoin_nearest()` method to join based on proximity, with the
ability to set a maximum search radius (#1865). In addition, the `sindex`
attribute gained a new method for a "nearest" spatial index query (#1865,
#2053).
- A new `explore()` method on GeoDataFrame and GeoSeries with native support
for interactive visualization based on folium / leaflet.js (#1953)
- The `geopandas.sjoin()`/`overlay()`/`clip()` functions are now also
available as methods on the GeoDataFrame (#2141, #1984, #2150).
New features and improvements:
- Add support for pandas' `value_counts()` method for geometry dtype (#2047).
- The `explode()` method has a new `ignore_index` keyword (consistent with
pandas' explode method) to reset the index in the result, and a new
`index_parts` keywords to control whether a cumulative count indexing the
parts of the exploded multi-geometries should be added (#1871).
- `points_from_xy()` is now available as a GeoSeries method `from_xy` (#1936).
- The `to_file()` method will now attempt to detect the driver (if not
specified) based on the extension of the provided filename, instead of
defaulting to ESRI Shapefile (#1609).
- Support for the `storage_options` keyword in `read_parquet()` for
specifying filesystem-specific options (e.g. for S3) based on fsspec (#2107).
- The read/write functions now support `~` (user home directory) expansion (#1876).
- Support the `convert_dtypes()` method from pandas to preserve the
GeoDataFrame class (#2115).
- Support WKB values in the hex format in `GeoSeries.from_wkb()` (#2106).
- Update the `estimate_utm_crs()` method to handle crossing the antimeridian
with pyproj 3.1+ (#2049).
- Improved heuristic to decide how many decimals to show in the repr based on
whether the CRS is projected or geographic (#1895).
- Switched the default for `geocode()` from GeoCode.Farm to the Photon
geocoding API (https://photon.komoot.io) (#2007).
Deprecations and compatibility notes:
- The `op=` keyword of `sjoin()` to indicate which spatial predicate to use
for joining is being deprecated and renamed in favor of a new `predicate=`
keyword (#1626).
- The `cascaded_union` attribute is deprecated, use `unary_union` instead (#2074).
- Constructing a GeoDataFrame with a duplicated "geometry" column is now
disallowed. This can also raise an error in the `pd.concat(.., axis=1)`
function if this results in duplicated active geometry columns (#2046).
- The `explode()` method currently returns a GeoSeries/GeoDataFrame with a
MultiIndex, with an additional level with indices of the parts of the
exploded multi-geometries. For consistency with pandas, this will change in
the future and the new `index_parts` keyword is added to control this.
Bug fixes:
- Fix in the `clip()` function to correctly clip MultiPoints instead of
leaving them intact when partly outside of the clip bounds (#2148).
- Fix `GeoSeries.isna()` to correctly return a boolean Series in case of an
empty GeoSeries (#2073).
- Fix the GeoDataFrame constructor to preserve the geometry name when the
argument is already a GeoDataFrame object (i.e. `GeoDataFrame(gdf)`) (#2138).
- Fix loss of the values' CRS when setting those values as a column
(`GeoDataFrame.__setitem__`) (#1963)
- Fix in `GeoDataFrame.apply()` to preserve the active geometry column name
(#1955).
- Fix in `sjoin()` to not ignore the suffixes in case of a right-join
(`how="right`) (#2065).
- Fix `GeoDataFrame.explode()` with a MultiIndex (#1945).
- Fix the handling of missing values in `to/from_wkb` and `to_from_wkt` (#1891).
- Fix `to_file()` and `to_json()` when DataFrame has duplicate columns to
raise an error (#1900).
- Fix bug in the colors shown with user-defined classification scheme (#2019).
- Fix handling of the `path_effects` keyword in `plot()` (#2127).
- Fix `GeoDataFrame.explode()` to preserve `attrs` (#1935)
Notes on (optional) dependencies:
- GeoPandas 0.10.0 dropped support for Python 3.6 and pandas 0.24. Further,
the minimum required versions are numpy 1.18, shapely 1.6, fiona 1.8,
matplotlib 3.1 and pyproj 2.2.
- Plotting with a classification schema now requires mapclassify version >=
2.4 (#1737).
- Compatibility fixes for the latest numpy in combination with Shapely 1.7 (#2072)
- Compatibility fixes for the upcoming Shapely 1.8 (#2087).
- Compatibility fixes for the latest PyGEOS (#1872, #2014) and matplotlib
(colorbar issue, #2066).
Version 0.9.0 (February 28, 2021)
---------------------------------
Many documentation improvements and a restyled and restructured website with
a new logo (#1564, #1579, #1617, #1668, #1731, #1750, #1757, #1759).
New features and improvements:
- The `geopandas.read_file` function now accepts more general
file-like objects (e.g. `fsspec` open file objects). It will now also
automatically recognize zipped files (#1535).
- The `GeoDataFrame.plot()` method now provides access to the pandas plotting
functionality for the non-geometry columns, either using the `kind` keyword
or the accessor method (e.g. `gdf.plot(kind="bar")` or `gdf.plot.bar()`)
(#1465).
- New `from_wkt()`, `from_wkb()`, `to_wkt()`, `to_wkb()` methods for
GeoSeries to construct a GeoSeries from geometries in WKT or WKB
representation, or to convert a GeoSeries to a pandas Seriew with WKT or WKB
values (#1710).
- New `GeoSeries.z` attribute to access the z-coordinates of Point geometries
(similar to the existing `.x` and `.y` attributes) (#1773).
- The `to_crs()` method now handles missing values (#1618).
- Support for pandas' new `.attrs` functionality (#1658).
- The `dissolve()` method now allows dissolving by no column (`by=None`) to
create a union of all geometries (single-row GeoDataFrame) (#1568).
- New `estimate_utm_crs()` method on GeoSeries/GeoDataFrame to determine the
UTM CRS based on the bounds (#1646).
- `GeoDataFrame.from_dict()` now accepts `geometry` and `crs` keywords
(#1619).
- `GeoDataFrame.to_postgis()` and `geopandas.read_postgis()` now supports
both sqlalchemy engine and connection objects (#1638).
- The `GeoDataFrame.explode()` method now allows exploding based on a
non-geometry column, using the pandas implementation (#1720).
- Performance improvement in `GeoDataFrame/GeoSeries.explode()` when using
the PyGEOS backend (#1693).
- The binary operation and predicate methods (eg `intersection()`,
`intersects()`) have a new `align` keyword which allows optionally not
aligning on the index before performing the operation with `align=False`
(#1668).
- The `GeoDataFrame.dissolve()` method now supports all relevant keywords of
`groupby()`, i.e. the `level`, `sort`, `observed` and `dropna` keywords
(#1845).
- The `geopandas.overlay()` function now accepts `make_valid=False` to skip
the step to ensure the input geometries are valid using `buffer(0)` (#1802).
- The `GeoDataFrame.to_json()` method gained a `drop_id` keyword to
optionally not write the GeoDataFrame's index as the "id" field in the
resulting JSON (#1637).
- A new `aspect` keyword in the plotting methods to optionally allow retaining
the original aspect (#1512)
- A new `interval` keyword in the `legend_kwds` group of the `plot()` method
to control the appearance of the legend labels when using a classification
scheme (#1605).
- The spatial index of a GeoSeries (accessed with the `sindex` attribute) is
now stored on the underlying array. This ensures that the spatial index is
preserved in more operations where possible, and that multiple geometry
columns of a GeoDataFrame can each have a spatial index (#1444).
- Addition of a `has_sindex` attribute on the GeoSeries/GeoDataFrame to check
if a spatial index has already been initialized (#1627).
- The `geopandas.testing.assert_geoseries_equal()` and `assert_geodataframe_equal()`
testing utilities now have a `normalize` keyword (False by default) to
normalize geometries before comparing for equality (#1826). Those functions
now also give a more informative error message when failing (#1808).
Deprecations and compatibility notes:
- The `is_ring` attribute currently returns True for Polygons. In the future,
this will be False (#1631). In addition, start to check it for LineStrings
and LinearRings (instead of always returning False).
- The deprecated `objects` keyword in the `intersection()` method of the
`GeoDataFrame/GeoSeries.sindex` spatial index object has been removed
(#1444).
Bug fixes:
- Fix regression in the `plot()` method raising an error with empty
geometries (#1702, #1828).
- Fix `geopandas.overlay()` to preserve geometries of the correct type which
are nested within a GeometryCollection as a result of the overlay
operation (#1582). In addition, a warning will now be raised if geometries
of different type are dropped from the result (#1554).
- Fix the repr of an empty GeoSeries to not show spurious warnings (#1673).
- Fix the `.crs` for empty GeoDataFrames (#1560).
- Fix `geopandas.clip` to preserve the correct geometry column name (#1566).
- Fix bug in `plot()` method when using `legend_kwds` with multiple subplots
(#1583)
- Fix spurious warning with `missing_kwds` keyword of the `plot()` method
when there are no areas with missing data (#1600).
- Fix the `plot()` method to correctly align values passed to the `column`
keyword as a pandas Series (#1670).
- Fix bug in plotting MultiPoints when passing values to determine the color
(#1694)
- The `rename_geometry()` method now raises a more informative error message
when a duplicate column name is used (#1602).
- Fix `explode()` method to preserve the CRS (#1655)
- Fix the `GeoSeries.apply()` method to again accept the `convert_dtype`
keyword to be consistent with pandas (#1636).
- Fix `GeoDataFrame.apply()` to preserve the CRS when possible (#1848).
- Fix bug in containment test as `geom in geoseries` (#1753).
- The `shift()` method of a GeoSeries/GeoDataFrame now preserves the CRS
(#1744).
- The PostGIS IO functionality now quotes table names to ensure it works with
case-sensitive names (#1825).
- Fix the `GeoSeries` constructor without passing data but only an index (#1798).
Notes on (optional) dependencies:
- GeoPandas 0.9.0 dropped support for Python 3.5. Further, the minimum
required versions are pandas 0.24, numpy 1.15 and shapely 1.6 and fiona 1.8.
- The `descartes` package is no longer required for plotting polygons. This
functionality is now included by default in GeoPandas itself, when
matplotlib is available (#1677).
- Fiona is now only imported when used in `read_file`/`to_file`. This means
you can now force geopandas to install without fiona installed (although it
is still a default requirement) (#1775).
- Compatibility with the upcoming Shapely 1.8 (#1659, #1662, #1819).
Version 0.8.2 (January 25, 2021)
--------------------------------
Small bug-fix release for compatibility with PyGEOS 0.9.
Version 0.8.1 (July 15, 2020)
-----------------------------
Small bug-fix release:
- Fix a regression in the `plot()` method when visualizing with a
JenksCaspallSampled or FisherJenksSampled scheme (#1486).
- Fix spurious warning in `GeoDataFrame.to_postgis` (#1497).
- Fix the un-pickling with `pd.read_pickle` of files written with older
GeoPandas versions (#1511).
Version 0.8.0 (June 24, 2020)
-----------------------------
**Experimental**: optional use of PyGEOS to speed up spatial operations (#1155).
PyGEOS is a faster alternative for Shapely (being contributed back to a future
version of Shapely), and is used in element-wise spatial operations and for
spatial index in e.g. `sjoin` (#1343, #1401, #1421, #1427, #1428). See the
[installation docs](https://geopandas.readthedocs.io/en/latest/install.html#using-the-optional-pygeos-dependency)
for more info and how to enable it.
New features and improvements:
- IO enhancements:
- New `GeoDataFrame.to_postgis()` method to write to PostGIS database (#1248).
- New Apache Parquet and Feather file format support (#1180, #1435)
- Allow appending to files with `GeoDataFrame.to_file` (#1229).
- Add support for the `ignore_geometry` keyword in `read_file` to only read
the attribute data. If set to True, a pandas DataFrame without geometry is
returned (#1383).
- `geopandas.read_file` now supports reading from file-like objects (#1329).
- `GeoDataFrame.to_file` now supports specifying the CRS to write to the file
(#802). By default it still uses the CRS of the GeoDataFrame.
- New `chunksize` keyword in `geopandas.read_postgis` to read a query in
chunks (#1123).
- Improvements related to geometry columns and CRS:
- Any column of the GeoDataFrame that has a "geometry" dtype is now returned
as a GeoSeries. This means that when having multiple geometry columns, not
only the "active" geometry column is returned as a GeoSeries, but also
accessing another geometry column (`gdf["other_geom_column"]`) gives a
GeoSeries (#1336).
- Multiple geometry columns in a GeoDataFrame can now each have a different
CRS. The global `gdf.crs` attribute continues to returns the CRS of the
"active" geometry column. The CRS of other geometry columns can be accessed
from the column itself (eg `gdf["other_geom_column"].crs`) (#1339).
- New `set_crs()` method on GeoDataFrame/GeoSeries to set the CRS of naive
geometries (#747).
- Improvements related to plotting:
- The y-axis is now scaled depending on the center of the plot when using a
geographic CRS, instead of using an equal aspect ratio (#1290).
- When passing a column of categorical dtype to the `column=` keyword of the
GeoDataFrame `plot()`, we now honor all categories and its order (#1483).
In addition, a new `categories` keyword allows to specify all categories
and their order otherwise (#1173).
- For choropleths using a classification scheme (using `scheme=`), the
`legend_kwds` accept two new keywords to control the formatting of the
legend: `fmt` with a format string for the bin edges (#1253), and `labels`
to pass fully custom class labels (#1302).
- New `covers()` and `covered_by()` methods on GeoSeries/GeoDataframe for the
equivalent spatial predicates (#1460, #1462).
- GeoPandas now warns when using distance-based methods with data in a
geographic projection (#1378).
Deprecations:
- When constructing a GeoSeries or GeoDataFrame from data that already has a
CRS, a deprecation warning is raised when both CRS don't match, and in the
future an error will be raised in such a case. You can use the new `set_crs`
method to override an existing CRS. See
[the docs](https://geopandas.readthedocs.io/en/latest/projections.html#projection-for-multiple-geometry-columns).
- The helper functions in the `geopandas.plotting` module are deprecated for
public usage (#656).
- The `geopandas.io` functions are deprecated, use the top-level `read_file` and
`to_file` instead (#1407).
- The set operators (`&`, `|`, `^`, `-`) are deprecated, use the
`intersection()`, `union()`, `symmetric_difference()`, `difference()` methods
instead (#1255).
- The `sindex` for empty dataframe will in the future return an empty spatial
index instead of `None` (#1438).
- The `objects` keyword in the `intersection` method of the spatial index
returned by the `sindex` attribute is deprecated and will be removed in the
future (#1440).
Bug fixes:
- Fix the `total_bounds()` method to ignore missing and empty geometries (#1312).
- Fix `geopandas.clip` when masking with non-overlapping area resulting in an
empty GeoDataFrame (#1309, #1365).
- Fix error in `geopandas.sjoin` when joining on an empty geometry column (#1318).
- CRS related fixes: `pandas.concat` preserves CRS when concatenating GeoSeries
objects (#1340), preserve the CRS in `geopandas.clip` (#1362) and in
`GeoDataFrame.astype` (#1366).
- Fix bug in `GeoDataFrame.explode()` when 'level_1' is one of the column names
(#1445).
- Better error message when rtree is not installed (#1425).
- Fix bug in `GeoSeries.equals()` (#1451).
- Fix plotting of multi-part geometries with additional style keywords (#1385).
And we now have a [Code of Conduct](https://github.com/geopandas/geopandas/blob/main/CODE_OF_CONDUCT.md)!
GeoPandas 0.8.0 is the last release to support Python 3.5. The next release
will require Python 3.6, pandas 0.24, numpy 1.15 and shapely 1.6 or higher.
Version 0.7.0 (February 16, 2020)
---------------------------------
@@ -87,10 +437,13 @@ Important note! This will be the last release to support Python 2.7 (#1031)
API changes:
- A refactor of the internals based on the pandas ExtensionArray interface (#1000). The main user visible changes are:
- The `.dtype` of a GeoSeries is now a `'geometry'` dtype (and no longer a numpy `object` dtype).
- The `.values` of a GeoSeries now returns a custom `GeometryArray`, and no longer a numpy array. To get back a numpy array of Shapely scalars, you can convert explicitly using `np.asarray(..)`.
- The `GeoSeries` constructor now raises a warning when passed non-geometry data. Currently the constructor falls back to return a pandas `Series`, but in the future this will raise an error (#1085).
- The missing value handling has been changed to now separate the concepts of missing geometries and empty geometries (#601, 1062). In practice this means that (see [the docs](https://geopandas.readthedocs.io/en/v0.6.0/missing_empty.html) for more details):
- `GeoSeries.isna` now considers only missing values, and if you want to check for empty geometries, you can use `GeoSeries.is_empty` (`GeoDataFrame.isna` already only looked at missing values).
- `GeoSeries.dropna` now actually drops missing values (before it didn't drop either missing or empty geometries)
- `GeoSeries.fillna` only fills missing values (behaviour unchanged).
@@ -133,16 +486,20 @@ Improvements:
* Significant performance improvement (around 10x) for `GeoDataFrame.iterfeatures`,
which also improves `GeoDataFrame.to_file` (#864).
* File IO enhancements based on Fiona 1.8:
* Support for writing bool dtype (#855) and datetime dtype, if the file format supports it (#728).
* Support for writing dataframes with multiple geometry types, if the file format allows it (e.g. GeoJSON for all types, or ESRI Shapefile for Polygon+MultiPolygon) (#827, #867, #870).
* Compatibility with pyproj >= 2 (#962).
* A new `geopandas.points_from_xy()` helper function to convert x and y coordinates to Point objects (#896).
* The `buffer` and `interpolate` methods now accept an array-like to specify a variable distance for each geometry (#781).
* The `buffer` and `interpolate` methods now accept an array-like to specify a variable distance for each geometry (#781).
* Addition of a `relate` method, corresponding to the shapely method that returns the DE-9IM matrix (#853).
* Plotting improvements:
* Performance improvement in plotting by only flattening the geometries if there are actually 'Multi' geometries (#785).
* Choropleths: access to all `mapclassify` classification schemes and addition of the `classification_kwds` keyword in the `plot` method to specify options for the scheme (#876).
* Ability to specify a matplotlib axes object on which to plot the color bar with the `cax` keyword, in order to have more control over the color bar placement (#894).
* Changed the default provider in ``geopandas.tools.geocode`` from Google (now requires an API key) to Geocode.Farm (#907, #975).
Bug fixes:
@@ -186,7 +543,7 @@ Improvements:
* Permit setting markersize for Point GeoSeries plots with column values (#633)
* Started an example gallery (#463, #690, #717)
* Support for plotting MultiPoints (#683)
* Testing functionalty (e.g. `assert_geodataframe_equal`) is now publicly exposed (#707)
* Testing functionality (e.g. `assert_geodataframe_equal`) is now publicly exposed (#707)
* Add `explode` method to GeoDataFrame (similar to the GeoSeries method) (#671)
* Set equal aspect on active axis on multi-axis figures (#718)
* Pass array of values to column argument in `plot` (#770)
+7 -9
View File
@@ -10,8 +10,8 @@ readable code. Performance matters, but not at the expense of those
goals.
In general, GeoPandas follows the conventions of the pandas project
where applicable. Please read the [pandas contributing
guidelines](http://pandas.pydata.org/pandas-docs/stable/contributing.html).
where applicable. Please read the [contributing
guidelines](https://geopandas.readthedocs.io/en/latest/community/contributing.html).
In particular, when submitting a pull request:
@@ -19,14 +19,12 @@ In particular, when submitting a pull request:
- Install the requirements for the development environment (one can do this
with either conda, and the environment.yml file, or pip, and the
requirements-dev.txt file, and can use the pandas contributing guidelines
as a guide).
as a guide).
- All existing tests should pass. Please make sure that the test
suite passes, both locally and on
[Travis CI](https://travis-ci.org/geopandas/geopandas). Status on
Travis will be visible on a pull request. If you want to enable
Travis CI on your own fork, please read the pandas guidelines link
above or the
[getting started docs](http://about.travis-ci.org/docs/user/getting-started/).
[GitHub Actions](https://github.com/geopandas/geopandas/actions). Status on
GHA will be visible on a pull request. GHA are automatically enabled
on your own fork as well. To trigger a check, make a PR to your own fork.
- New functionality should include tests. Please write reasonable
tests for your code and make sure that they pass on your pull request.
@@ -41,7 +39,7 @@ is a great way to get started if you'd like to make a contribution.
Style
-----
- GeoPandas supports Python 3.5+ only. The last version of GeoPandas
- GeoPandas supports Python 3.7+ only. The last version of GeoPandas
supporting Python 2 is 0.6.
- GeoPandas follows [the PEP 8
+24 -21
View File
@@ -1,4 +1,4 @@
GeoPandas [![build status](https://secure.travis-ci.org/geopandas/geopandas.png?branch=master)](https://travis-ci.org/geopandas/geopandas) [![Coverage Status](https://codecov.io/gh/geopandas/geopandas/branch/master/graph/badge.svg)](https://codecov.io/gh/geopandas/geopandas) [![Join the chat at https://gitter.im/geopandas/geopandas](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/geopandas/geopandas?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/geopandas/geopandas/master) [![DOI](https://zenodo.org/badge/11002815.svg)](https://zenodo.org/badge/latestdoi/11002815)
GeoPandas [![Actions Status](https://github.com/geopandas/geopandas/workflows/Tests/badge.svg)](https://github.com/geopandas/geopandas/actions?query=workflow%3ATests) [![Coverage Status](https://codecov.io/gh/geopandas/geopandas/branch/main/graph/badge.svg)](https://codecov.io/gh/geopandas/geopandas) [![Join the chat at https://gitter.im/geopandas/geopandas](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/geopandas/geopandas?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/geopandas/geopandas/main) [![DOI](https://zenodo.org/badge/11002815.svg)](https://zenodo.org/badge/latestdoi/11002815)
=========
Python tools for geographic data
@@ -35,8 +35,9 @@ for all details. GeoPandas depends on the following packages:
- ``shapely``
- ``fiona``
- ``pyproj``
- ``packaging``
Further, ``descartes`` and ``matplotlib`` are optional dependencies, required
Further, ``matplotlib`` is an optional dependency, required
for plotting, and [``rtree``](https://github.com/Toblerity/rtree) is an optional
dependency, required for spatial joins. ``rtree`` requires the C library [``libspatialindex``](https://github.com/libspatialindex/libspatialindex).
@@ -67,7 +68,7 @@ Examples
2 POLYGON ((2 0, 3 0, 3 1, 2 1, 2 0))
dtype: geometry
![Example 1](examples/test.png)
![Example 1](doc/source/gallery/test.png)
Some geographic operations return normal pandas object. The `area` property of a `GeoSeries` will return a `pandas.Series` containing the area of each item in the `GeoSeries`:
@@ -85,9 +86,11 @@ Other operations return GeoPandas objects:
2 POLYGON ((1.5 0, 1.5 1, 1.502407636663901 1.04...
dtype: geometry
![Example 2](examples/test_buffer.png)
![Example 2](doc/source/gallery/test_buffer.png)
GeoPandas objects also know how to plot themselves. GeoPandas uses [descartes](https://pypi.python.org/pypi/descartes) to generate a [matplotlib](http://matplotlib.org) plot. To generate a plot of our GeoSeries, use:
GeoPandas objects also know how to plot themselves. GeoPandas uses
[matplotlib](http://matplotlib.org) for plotting. To generate a plot of our
GeoSeries, use:
>>> g.plot()
@@ -99,22 +102,22 @@ GeoPandas also implements alternate constructors that can read any data format r
>>> boros.sort_index(inplace=True)
>>> boros
BoroName Shape_Leng Shape_Area \
BoroCode
1 Manhattan 359299.096471 6.364715e+08
2 Bronx 464392.991824 1.186925e+09
3 Brooklyn 741080.523166 1.937479e+09
4 Queens 896344.047763 3.045213e+09
5 Staten Island 330470.010332 1.623820e+09
geometry
BoroCode
1 MULTIPOLYGON (((981219.0557861328 188655.31579...
2 MULTIPOLYGON (((1012821.805786133 229228.26458...
3 MULTIPOLYGON (((1021176.479003906 151374.79699...
4 MULTIPOLYGON (((1029606.076599121 156073.81420...
5 MULTIPOLYGON (((970217.0223999023 145643.33221...
BoroCode
1 Manhattan 359299.096471 6.364715e+08
2 Bronx 464392.991824 1.186925e+09
3 Brooklyn 741080.523166 1.937479e+09
4 Queens 896344.047763 3.045213e+09
5 Staten Island 330470.010332 1.623820e+09
![New York City boroughs](examples/nyc.png)
geometry
BoroCode
1 MULTIPOLYGON (((981219.0557861328 188655.31579...
2 MULTIPOLYGON (((1012821.805786133 229228.26458...
3 MULTIPOLYGON (((1021176.479003906 151374.79699...
4 MULTIPOLYGON (((1029606.076599121 156073.81420...
5 MULTIPOLYGON (((970217.0223999023 145643.33221...
![New York City boroughs](doc/source/gallery/nyc.png)
>>> boros['geometry'].convex_hull
BoroCode
@@ -125,4 +128,4 @@ GeoPandas also implements alternate constructors that can read any data format r
5 POLYGON ((915517.6877458114 120121.8812543372,...
dtype: geometry
![Convex hulls of New York City boroughs](examples/nyc_hull.png)
![Convex hulls of New York City boroughs](doc/source/gallery/nyc_hull.png)
-46
View File
@@ -1,46 +0,0 @@
# With infos from
# http://tjelvarolsson.com/blog/how-to-continuously-test-your-python-code-on-windows-using-appveyor/
# https://packaging.python.org/en/latest/appveyor/
# https://github.com/rmcgibbo/python-appveyor-conda-example
environment:
matrix:
- PYTHON_VERSION: "3.7"
MINICONDA: C:\Miniconda37-x64
ENV_FILE: "ci/travis/37-latest-conda-forge.yaml"
- PYTHON_VERSION: "3.8"
MINICONDA: C:\Miniconda37-x64
ENV_FILE: "ci/travis/38-latest-conda-forge.yaml"
# all our python builds have to happen in tests_script...
build: false
init:
- "ECHO %PYTHON_VERSION% %MINICONDA%"
install:
# cancel older builds for the same PR
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
throw "There are newer queued builds for this pull request, failing early." }
# set up environment
- CALL "%MINICONDA%\\Scripts\\activate.bat"
- conda config --set always_yes yes --set show_channel_urls true --set changeps1 no
- conda update conda
# this is basically equivalent to what conda init does. It changes the "conda" to
# be a .bat script that sets appropriate PATH entries before conda hits problems.
# This PATH modification only works with conda 4.6+, but it won't hurt other versions.
- set "PATH=%MINICONDA%\condabin:%PATH%"
- conda info -a
- conda config --add channels conda-forge
- conda config --set channel_priority strict
- conda env create --file="${ENV_FILE}"
test_script:
# this uses condabin/conda.bat because of our PATH modification above
- conda activate test
- conda list
- pytest geopandas -v
+10 -2
View File
@@ -2,7 +2,7 @@ import random
import numpy as np
from geopandas import GeoSeries
from shapely.geometry import Point, LineString, Polygon
from shapely.geometry import Point, Polygon, MultiPolygon
def with_attributes(**attrs):
@@ -25,10 +25,15 @@ class Bench:
triangles3 = GeoSeries([Polygon([(random.random(), random.random())
for _ in range(3)])
for _ in range(10000)])
triangles4 = GeoSeries([
MultiPolygon([
Polygon([(random.random(), random.random()) for _ in range(3)])
]) for _ in range(10000)])
triangle = Polygon([(random.random(), random.random())
for _ in range(3)])
self.triangles, self.triangles2 = triangles, triangles2
self.triangles_big = triangles3
self.multi_triangles = triangles4
self.triangle = triangle
@with_attributes(param_names=['op'],
@@ -98,7 +103,10 @@ class Bench:
def time_buffer(self, *args):
self.points.buffer(2)
def time_explode(self, *args):
self.multi_triangles.explode()
# TODO
# project, interpolate, affine_transform, translate, rotate, scale, skew, explode
# project, interpolate, affine_transform, translate, rotate, scale, skew
# cx indexer
+27 -7
View File
@@ -1,10 +1,11 @@
from geopandas import GeoDataFrame, GeoSeries, read_file, datasets, overlay
from shapely.geometry import Polygon
import numpy as np
from shapely.geometry import Point, Polygon
class Countries:
param_names = ['op']
param_names = ['how']
params = [('intersection', 'union', 'identity', 'symmetric_difference',
'difference')]
@@ -20,13 +21,13 @@ class Countries:
self.countries = countries
self.capitals = capitals
def time_overlay(self, op):
overlay(self.countries, self.capitals, how=op)
def time_overlay(self, how):
overlay(self.countries, self.capitals, how=how)
class Small:
param_names = ['op']
param_names = ['how']
params = [('intersection', 'union', 'identity', 'symmetric_difference',
'difference')]
@@ -41,5 +42,24 @@ class Small:
self.df1, self.df2 = df1, df2
def time_overlay(self, op):
overlay(self.df1, self.df2, how=op)
def time_overlay(self, how):
overlay(self.df1, self.df2, how=how)
class ManyPoints:
param_names = ['how']
params = [('intersection', 'union', 'identity', 'symmetric_difference',
'difference')]
def setup(self, *args):
points = GeoDataFrame(geometry=[Point(i, i) for i in range(1000)])
base = np.array([[0, 0], [0, 100], [100, 100], [100, 0]])
polys = GeoDataFrame(
geometry=[Polygon(base + i * 100) for i in range(10)])
self.df1, self.df2 = points, polys
def time_overlay(self, how):
overlay(self.df1, self.df2, how=how)
+47 -29
View File
@@ -7,44 +7,63 @@ import numpy as np
class Bench:
param_names = ['geom_type']
params = [('Point', 'LineString', 'Polygon', 'MultiPolygon', 'mixed')]
param_names = ["geom_type"]
params = [("Point", "LineString", "Polygon", "MultiPolygon", "mixed")]
def setup(self, geom_type):
if geom_type == 'Point':
if geom_type == "Point":
geoms = GeoSeries([Point(i, i) for i in range(1000)])
elif geom_type == 'LineString':
geoms = GeoSeries([LineString([(random.random(), random.random())
for _ in range(5)])
for _ in range(100)])
elif geom_type == 'Polygon':
geoms = GeoSeries([Polygon([(random.random(), random.random())
for _ in range(3)])
for _ in range(100)])
elif geom_type == 'MultiPolygon':
elif geom_type == "LineString":
geoms = GeoSeries(
[MultiPolygon([Polygon([(random.random(), random.random())
for _ in range(3)])
for _ in range(3)])
for _ in range(20)])
elif geom_type == 'mixed':
[
LineString([(random.random(), random.random()) for _ in range(5)])
for _ in range(100)
]
)
elif geom_type == "Polygon":
geoms = GeoSeries(
[
Polygon([(random.random(), random.random()) for _ in range(3)])
for _ in range(100)
]
)
elif geom_type == "MultiPolygon":
geoms = GeoSeries(
[
MultiPolygon(
[
Polygon(
[(random.random(), random.random()) for _ in range(3)]
)
for _ in range(3)
]
)
for _ in range(20)
]
)
elif geom_type == "mixed":
g1 = GeoSeries([Point(i, i) for i in range(100)])
g2 = GeoSeries([LineString([(random.random(), random.random())
for _ in range(5)])
for _ in range(100)])
g3 = GeoSeries([Polygon([(random.random(), random.random())
for _ in range(3)])
for _ in range(100)])
g2 = GeoSeries(
[
LineString([(random.random(), random.random()) for _ in range(5)])
for _ in range(100)
]
)
g3 = GeoSeries(
[
Polygon([(random.random(), random.random()) for _ in range(3)])
for _ in range(100)
]
)
geoms = g1
geoms.iloc[np.random.randint(0, 100, 50)] = g2
geoms.iloc[np.random.randint(0, 100, 33)] = g3
geoms.iloc[np.random.randint(0, 100, 50)] = g2.iloc[:50]
geoms.iloc[np.random.randint(0, 100, 33)] = g3.iloc[:33]
print(geoms.geom_type.value_counts())
df = GeoDataFrame({'geometry': geoms,
'values': np.random.randn(len(geoms))})
df = GeoDataFrame({"geometry": geoms, "values": np.random.randn(len(geoms))})
self.geoms = geoms
self.df = df
@@ -53,5 +72,4 @@ class Bench:
self.geoms.plot()
def time_plot_values(self, *args):
self.df.plot(column='values')
self.df.plot(column="values")
+64 -24
View File
@@ -1,5 +1,14 @@
from geopandas import read_file, datasets
from geopandas.sindex import VALID_QUERY_PREDICATES
from shapely.geometry import Point
from geopandas import read_file, datasets, GeoSeries
# Derive list of valid query predicates based on underlying index backend;
# we have to create a non-empty instance of the index to get these
index = GeoSeries([Point(0, 0)]).sindex
predicates = sorted(p for p in index.valid_query_predicates if p is not None)
geom_types = ("mixed", "points", "polygons")
def generate_test_df():
@@ -16,44 +25,70 @@ def generate_test_df():
"points": points[points.is_valid],
"polygons": polygons[polygons.is_valid],
}
# ensure index is pre-generated
for data_type in data.keys():
data[data_type].sindex.query(data[data_type].geometry.values.data[0])
return data
class Bench:
class BenchIntersection:
param_names = ["tree_geom_type"]
params = [["mixed", "points", "polygons"]]
param_names = ["input_geom_type", "tree_geom_type"]
params = [
geom_types,
geom_types,
]
def setup(self, *args):
self.data = generate_test_df()
# cache bounds so that bound creation is not counted in benchmarks
self.bounds = [g.bounds for g in self.data["mixed"].geometry]
self.bounds = {
data_type: [g.bounds for g in self.data[data_type].geometry]
for data_type in self.data.keys()
}
def time_intersects(self, input_geom_type, tree_geom_type):
tree = self.data[tree_geom_type].sindex
for bounds in self.bounds[input_geom_type]:
tree.intersection(bounds)
class BenchIndexCreation:
param_names = ["tree_geom_type"]
params = [
geom_types,
]
def setup(self, *args):
self.data = generate_test_df()
def time_index_creation(self, tree_geom_type):
"""Time creation of spatial index.
Note: pygeos will only create the index once; this benchmark
is not intended to be used to compare rtree and pygeos.
Note: requires running a single query to ensure that
lazy-building indexes are actually built.
"""
self.data[tree_geom_type]._invalidate_sindex()
self.data[tree_geom_type]._generate_sindex()
def time_intersects(self, tree_geom_type):
for bounds in self.bounds:
self.data[tree_geom_type].sindex.intersection(bounds)
def time_intersects_objects(self, tree_geom_type):
for bounds in self.bounds:
self.data[tree_geom_type].sindex.intersection(bounds, objects=True)
# Note: the GeoDataFram._sindex_generated attribute will
# be removed by GH#1444 but is kept here (in the benchmarks
# so that we can compare pre GH#1444 to post GH#1444 if needed
self.data[tree_geom_type]._sindex_generated = None
self.data[tree_geom_type].geometry.values._sindex = None
tree = self.data[tree_geom_type].sindex
# also do a single query to ensure the index is actually
# generated and used
tree.query(
self.data[tree_geom_type].geometry.values.data[0]
)
class BenchQuery:
param_names = ["predicate", "input_geom_type", "tree_geom_type"]
params = [
[*VALID_QUERY_PREDICATES],
["mixed", "points", "polygons"],
["mixed", "points", "polygons"],
predicates,
geom_types,
geom_types,
]
def setup(self, *args):
@@ -61,9 +96,14 @@ class BenchQuery:
def time_query_bulk(self, predicate, input_geom_type, tree_geom_type):
self.data[tree_geom_type].sindex.query_bulk(
self.data[input_geom_type].geometry, predicate=predicate
self.data[input_geom_type].geometry.values.data,
predicate=predicate,
)
def time_query(self, predicate, input_geom_type, tree_geom_type):
for geo in self.data[input_geom_type].geometry.sample(10, random_state=0):
self.data[tree_geom_type].sindex.query(geo, predicate=predicate)
tree = self.data[tree_geom_type].sindex
for geom in self.data[input_geom_type].geometry.values.data:
tree.query(
geom,
predicate=predicate
)
+2 -2
View File
@@ -26,5 +26,5 @@ class Bench:
self.df1, self.df2 = df1, df2
def time_sjoin(self, op):
sjoin(self.df1, self.df2, op=op)
def time_sjoin(self, predicate):
sjoin(self.df1, self.df2, predicate=predicate)
+36
View File
@@ -0,0 +1,36 @@
name: test
channels:
- conda-forge
dependencies:
- python=3.10
- cython
# required
- shapely
- fiona
- pyproj
- geos
- packaging
# testing
- pytest
- pytest-cov
- pytest-xdist
- fsspec
# optional
- rtree
#- geopy
- SQLalchemy
- libspatialite
- pyarrow
- pip
- pip:
- geopy
- mapclassify>=2.4.0
# dev versions of packages
- --pre --extra-index https://pypi.anaconda.org/scipy-wheels-nightly/simple
- numpy
- pandas
- git+https://github.com/matplotlib/matplotlib.git@main
# - git+https://github.com/Toblerity/Shapely.git@main
- git+https://github.com/pygeos/pygeos.git@master
- git+https://github.com/python-visualization/folium.git@main
- git+https://github.com/geopandas/xyzservices.git@main
+34
View File
@@ -0,0 +1,34 @@
name: test
channels:
- conda-forge
dependencies:
- python=3.10
# required
- pandas
- shapely
- fiona
- pyproj
- pygeos
- packaging
# testing
- pytest
- pytest-cov
- pytest-xdist
- fsspec
# optional
- rtree
- matplotlib-base
- mapclassify
- folium
- xyzservices
- scipy
- geopy
# installed in tests.yaml, because not available on windows
# - postgis
- SQLalchemy
- psycopg2
- libspatialite
- geoalchemy2
- pyarrow
# doctest testing
- pytest-doctestplus
@@ -9,15 +9,19 @@ dependencies:
- fiona
- pyproj
- pygeos
- packaging
# testing
- pytest
- pytest-cov
- codecov
- pytest-xdist
- fsspec
# optional
- rtree
- matplotlib
- descartes
- mapclassify
- folium
- xyzservices
- scipy
- geopy
- SQLalchemy
- libspatialite
@@ -2,27 +2,29 @@ name: test
channels:
- defaults
dependencies:
- python=3.7.3
- python=3.7
# required
- pandas
- shapely
- fiona
- pyproj
- geos
- packaging
# testing
- pytest
- pytest-cov
#- codecov
- pytest-xdist
- fsspec
# optional
- rtree
- matplotlib
- descartes
#- geopy
- SQLalchemy
- libspatialite
- pyarrow
- pip
- pip:
- codecov
- geopy
- mapclassify
- git+https://github.com/pygeos/pygeos.git
- geopy
- mapclassify
- pyarrow
- folium
- xyzservices
@@ -3,26 +3,28 @@ channels:
- defaults
- conda-forge
dependencies:
- python=3.5
- python=3.7
# required
- numpy=1.12
- pandas==0.23.4
- shapely=1.5
- fiona=1.7
- numpy=1.18
- pandas==0.25
- shapely=1.6
- fiona=1.8.13
- packaging
#- pyproj
# testing
- pytest
- pytest-cov
- codecov
- pytest-xdist
- fsspec
# optional
- rtree
- matplotlib
- descartes
- matplotlib=2.0
- mapclassify>=2.2.0
- matplotlib=3.1
# - mapclassify=2.4.0 - doesn't build due to conflicts
- geopy
- SQLalchemy
- libspatialite
- pyarrow
- pip
- pip:
- pyproj==2.2.2
- pyproj==2.2.2
+12 -11
View File
@@ -2,28 +2,29 @@ name: test
channels:
- defaults
dependencies:
- python=3.7.3
- cython
- python=3.7
# required
- pandas
- pandas=1.0
- shapely
- fiona
- pyproj
- numpy=<1.19
#- pyproj
- geos
- packaging
# testing
- pytest
- pytest-cov
#- codecov
- pytest-xdist
- fsspec
# optional
- rtree
- matplotlib
- descartes
#- geopy
- SQLalchemy
- libspatialite
- pyarrow
- pip
- pip:
- codecov
- geopy
- mapclassify>=2.2.0
- git+https://github.com/pygeos/pygeos.git
- pyproj==3.0.1
- geopy
- mapclassify==2.4.0
- pyarrow
@@ -4,25 +4,31 @@ channels:
dependencies:
- python=3.8
# required
- pandas
- pandas=1.2
- shapely
- fiona
- pyproj
- pygeos
- packaging
# testing
- pytest
- pytest-cov
- codecov
- pytest-xdist
- fsspec
# optional
- rtree
- matplotlib
- descartes
- mapclassify
- folium
- xyzservices
- scipy
- geopy
# installed in travis.yml, because not available on windows
# installed in tests.yaml, because not available on windows
# - postgis
- SQLalchemy
- psycopg2
- libspatialite
- geoalchemy2
- pyarrow
# doctest testing
- pytest-doctestplus
@@ -8,7 +8,8 @@ dependencies:
- shapely
- fiona
- pyproj
- packaging
# testing
- pytest
- pytest-cov
- codecov
- pytest-xdist
+35
View File
@@ -0,0 +1,35 @@
name: test
channels:
- conda-forge
dependencies:
- python=3.9
# required
- pandas=1.3
- shapely
- fiona
- pyproj
- pygeos
- packaging
# testing
- pytest
- pytest-cov
- pytest-xdist
- fsspec
# optional
- rtree
- matplotlib
- mapclassify
- folium
- xyzservices
- scipy
- geopy
# installed in tests.yaml, because not available on windows
# - postgis
- SQLalchemy
- psycopg2
- libspatialite
- geoalchemy2
- pyarrow
# doctest testing
- pytest-doctestplus
+33
View File
@@ -0,0 +1,33 @@
#!/bin/sh
set -e
if [ -z "${PGUSER}" ] || [ -z "${PGPORT}" ]; then
echo "Environment variables PGUSER and PGPORT must be set"
exit 1
fi
PGDATA=$(mktemp -d /tmp/postgres.XXXXXX)
echo "Setting up PostgreSQL in ${PGDATA} on port ${PGPORT}"
pg_ctl -D ${PGDATA} initdb
pg_ctl -D ${PGDATA} start
SOCKETPATH="/tmp/.s.PGSQL.${PGPORT}"
echo -n 'waiting for postgres'
while [ ! -e ${SOCKETPATH} ]; do
sleep 1
echo -n '.'
done
echo
echo "Done setting up PostgreSQL. When finished, stop and cleanup using:"
echo
echo " pg_ctl -D ${PGDATA} stop"
echo " rm -rf ${PGDATA}"
echo
createuser -U ${USER} -s ${PGUSER}
createdb --owner=${PGUSER} test_geopandas
psql -d test_geopandas -q -c "CREATE EXTENSION postgis"
echo "PostGIS server ready."
-31
View File
@@ -1,31 +0,0 @@
name: test
channels:
- defaults
dependencies:
- python=3.6
- pip
# required
- pandas==0.23.4
- nomkl
- shapely
- gdal=2.3
- fiona
#- pyproj
- geos
# testing
- pytest
- pytest-cov
#- codecov
# optional
- rtree
- matplotlib=2
- descartes
#- geopy
- SQLalchemy
- libspatialite
- pip:
- pyproj==2.3.1
- geopy
- codecov
- mapclassify>=2.2.0
- git+https://github.com/pygeos/pygeos.git
-29
View File
@@ -1,29 +0,0 @@
name: test
channels:
- defaults
dependencies:
- python=3.6
# required
- pandas=0.24
- shapely
- fiona=1.7
#- pyproj
- geos
# testing
- pytest
- pytest-cov
#- codecov
# optional
- rtree
- matplotlib==2.0.2
- descartes
#- geopy
- SQLalchemy
- libspatialite
- pyarrow
- pip:
- pyproj
- codecov
- geopy
- mapclassify>=2.2.0
- git+https://github.com/pygeos/pygeos.git
-21
View File
@@ -1,21 +0,0 @@
#!/bin/bash -e
echo "Setting up Postgresql"
mkdir -p ${HOME}/var
rm -rf ${HOME}/var/db
pg_ctl initdb -D ${HOME}/var/db
pg_ctl start -D ${HOME}/var/db
echo -n 'waiting for postgres'
while [ ! -e /tmp/.s.PGSQL.5432 ]; do
sleep 1
echo -n '.'
done
createuser -U travis -s postgres
createdb --owner=postgres test_geopandas
psql -d test_geopandas -q -c "CREATE EXTENSION postgis"
echo "Done setting up Postgresql"
+6
View File
@@ -0,0 +1,6 @@
coverage:
status:
project:
default:
target: 95% # the required coverage value
threshold: 0.2% # the leniency in hitting the target
-1
View File
@@ -41,7 +41,6 @@ help:
clean:
-rm -rf $(BUILDDIR)/*
-rm -rf source/reference/*
-rm -rf source/gallery/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+42 -31
View File
@@ -1,34 +1,45 @@
name: geopandas_docs
channels:
- conda-forge
- conda-forge
dependencies:
- python=3.7
- pandas=1.0.1
- shapely=1.7.0
- fiona=1.8.13
- pyproj=2.4.2.post1
- rtree=0.9.4
- geopy=1.21.0
- matplotlib=3.1.3
- descartes=1.1.0
- mapclassify=2.2.0
- sphinx=2.4.1
- sphinx_rtd_theme=0.4.3
- numpydoc=0.9.2
- recommonmark==0.6.0
- ipython=7.12.0
- pillow=7.0.0
- mock=3.0.5
- cartopy=0.17.0
- contextily=1.0rc2
- rasterio=1.1.1
- geoplot=0.4.0
# 0.5.0 has a bug (https://github.com/sphinx-gallery/sphinx-gallery/issues/568)
- sphinx-gallery=0.4.0
- jinja2=2.11.1
- doc2dash
# specify additional dependencies to reduce solving for conda
- gdal=3.0.4
- libgdal=3.0.4
- proj=6.3.0
- geos=3.8.0
- python=3.9.7
- pandas=1.3.2
- shapely=1.7.1
- fiona=1.8.20
- pyproj=3.2.1
- rtree=0.9.7
- geopy=2.2.0
- matplotlib=3.4.3
- mapclassify=2.4.3
- sphinx=4.2.0
- pydata-sphinx-theme=0.6.3
- numpydoc=1.1.0
- ipython=7.27.0
- pillow=8.3.2
- mock=4.0.3
- cartopy=0.20.0
- pyepsg=0.4.0
- contextily=1.1.0
- rasterio=1.2.8
- geoplot=0.4.4
- sphinx-gallery=0.9.0
- jinja2=3.0.1
- doc2dash=2.3.0
- matplotlib-scalebar=0.7.2
# specify additional dependencies to reduce solving for conda
- gdal=3.3.2
- libgdal=3.3.2
- proj=8.0.1
- geos=3.9.1
- nbsphinx=0.8.7
- jupyter_client=7.0.3
- ipykernel=6.4.1
- myst-parser=0.15.2
- folium=0.12.0
- libpysal=4.5.1
- pygeos=0.10.2
- xyzservices=2021.9.1
- packaging=21.0
- pip
- pip:
- sphinx-toggleprompt
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="105.44mm" height="35.61mm" viewBox="0 0 298.88 100.95"><line x1="120.15" y1="48.9" x2="162.49" y2="48.9" style="fill:none;stroke:#1d1d1b;stroke-miterlimit:10"/><polygon points="161.03 53.89 169.67 48.9 161.03 43.91 161.03 53.89" style="fill:#1d1d1b"/><circle cx="45.9" cy="48.9" r="34.98" style="fill:#e21c84;stroke:#fff;stroke-miterlimit:10;opacity:0.4"/><circle cx="80.88" cy="48.9" r="34.98" style="fill:#0f9c5a;stroke:#fff;stroke-miterlimit:10;opacity:0.6"/><g style="opacity:0.8"><circle cx="214.68" cy="48.9" r="34.98" style="fill:none;stroke:#fec905;stroke-miterlimit:10;stroke-dasharray:1.9972946643829346,1.9972946643829346"/></g><g style="opacity:0.8"><circle cx="249.65" cy="48.9" r="34.98" style="fill:none;stroke:#fec905;stroke-miterlimit:10;stroke-dasharray:1.9972946643829346,1.9972946643829346"/></g><path d="M214.68,48.9a35,35,0,0,1,17.48-30.29,35,35,0,1,0,0,60.57A34.93,34.93,0,0,1,214.68,48.9Z" style="fill:#fec905;opacity:0.8"/></svg>

After

Width:  |  Height:  |  Size: 1001 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="105.44mm" height="35.61mm" viewBox="0 0 298.88 100.95"><g style="opacity:0.8"><circle cx="214.68" cy="51.28" r="34.98" transform="matrix(0.94, -0.33, 0.33, 0.94, -4.87, 73.95)" style="fill:none;stroke:#fec905;stroke-miterlimit:10;stroke-dasharray:1.9972946643829346,1.9972946643829346"/></g><g style="opacity:0.8"><circle cx="249.65" cy="51.28" r="34.98" transform="translate(74.78 236.69) rotate(-58.28)" style="fill:none;stroke:#fec905;stroke-miterlimit:10;stroke-dasharray:1.9972946643829346,1.9972946643829346"/></g><line x1="120.15" y1="51.28" x2="162.49" y2="51.28" style="fill:none;stroke:#1d1d1b;stroke-miterlimit:10"/><polygon points="161.03 56.27 169.67 51.28 161.03 46.3 161.03 56.27" style="fill:#1d1d1b"/><circle cx="45.9" cy="51.28" r="34.98" style="fill:#e21c84;stroke:#fff;stroke-miterlimit:10;opacity:0.4"/><circle cx="80.88" cy="51.28" r="34.98" style="fill:#0f9c5a;stroke:#fff;stroke-miterlimit:10;opacity:0.6"/><ellipse cx="232.16" cy="51.28" rx="17.49" ry="30.29" style="fill:#fec905;opacity:0.8"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="105.44mm" height="35.61mm" viewBox="0 0 298.88 100.95"><g style="opacity:0.8"><circle cx="214.68" cy="51.28" r="34.98" transform="matrix(0.94, -0.33, 0.33, 0.94, -4.87, 73.95)" style="fill:none;stroke:#fec905;stroke-miterlimit:10;stroke-dasharray:1.9972946643829346,1.9972946643829346"/></g><g style="opacity:0.8"><circle cx="249.65" cy="51.28" r="34.98" transform="translate(74.78 236.69) rotate(-58.28)" style="fill:none;stroke:#fec905;stroke-miterlimit:10;stroke-dasharray:1.9972946643829346,1.9972946643829346"/></g><line x1="120.15" y1="51.28" x2="162.49" y2="51.28" style="fill:none;stroke:#1d1d1b;stroke-miterlimit:10"/><polygon points="161.03 56.27 169.67 51.28 161.03 46.3 161.03 56.27" style="fill:#1d1d1b"/><circle cx="45.9" cy="51.28" r="34.98" style="fill:#e21c84;stroke:#fff;stroke-miterlimit:10;opacity:0.4"/><circle cx="80.88" cy="51.28" r="34.98" style="fill:#0f9c5a;stroke:#fff;stroke-miterlimit:10;opacity:0.6"/><g style="opacity:0.8"><path d="M214.68,51.28A35,35,0,0,1,232.16,21a35,35,0,1,0,0,60.57A35,35,0,0,1,214.68,51.28Z" style="fill:#fec905"/><path d="M249.65,16.31A34.81,34.81,0,0,0,232.16,21a35,35,0,0,1,0,60.57,35,35,0,1,0,17.49-65.26Z" style="fill:#fec905"/></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="105.44mm" height="35.61mm" viewBox="0 0 298.88 100.95"><g style="opacity:0.8"><circle cx="214.68" cy="50.49" r="34.98" transform="matrix(0.94, -0.33, 0.33, 0.94, -4.61, 73.91)" style="fill:none;stroke:#fec905;stroke-miterlimit:10;stroke-dasharray:1.9972946643829346,1.9972946643829346"/></g><g style="opacity:0.8"><circle cx="249.65" cy="50.49" r="34.98" transform="translate(75.45 236.31) rotate(-58.28)" style="fill:none;stroke:#fec905;stroke-miterlimit:10;stroke-dasharray:1.9972946643829346,1.9972946643829346"/></g><line x1="120.15" y1="50.49" x2="162.49" y2="50.49" style="fill:none;stroke:#1d1d1b;stroke-miterlimit:10"/><polygon points="161.03 55.48 169.67 50.49 161.03 45.5 161.03 55.48" style="fill:#1d1d1b"/><circle cx="45.9" cy="50.49" r="34.98" style="fill:#e21c84;stroke:#fff;stroke-miterlimit:10;opacity:0.4"/><circle cx="80.88" cy="50.49" r="34.98" style="fill:#0f9c5a;stroke:#fff;stroke-miterlimit:10;opacity:0.6"/><path d="M249.65,15.51a34.91,34.91,0,0,0-17.49,4.69,35,35,0,1,0,0,60.57,35,35,0,1,0,17.49-65.26Z" style="fill:#fec905;opacity:0.8"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.4 KiB

+43
View File
@@ -0,0 +1,43 @@
"""
Create an illustrative figure for different kwargs
in buffer method.
"""
import geopandas
import matplotlib.pyplot as plt
from shapely.geometry import Point, LineString, Polygon
s = geopandas.GeoSeries(
[
Point(0, 0),
LineString([(1, -1), (1, 0), (2, 0), (2, 1)]),
Polygon([(3, -1), (4, 0), (3, 1)]),
]
)
fix, axs = plt.subplots(
3, 2, figsize=(12, 12), sharex=True, sharey=True
)
for ax in axs.flatten():
s.plot(ax=ax)
ax.set(xticks=[], yticks=[])
s.buffer(0.2).plot(ax=axs[0, 0], alpha=0.6)
axs[0, 0].set_title("s.buffer(0.2)")
s.buffer(0.2, resolution=2).plot(ax=axs[0, 1], alpha=0.6)
axs[0, 1].set_title("s.buffer(0.2, resolution=2)")
s.buffer(0.2, cap_style=2).plot(ax=axs[1, 0], alpha=0.6)
axs[1, 0].set_title("s.buffer(0.2, cap_style=2)")
s.buffer(0.2, cap_style=3).plot(ax=axs[1, 1], alpha=0.6)
axs[1, 1].set_title("s.buffer(0.2, cap_style=3)")
s.buffer(0.2, join_style=2).plot(ax=axs[2, 0], alpha=0.6)
axs[2, 0].set_title("s.buffer(0.2, join_style=2)")
s.buffer(0.2, join_style=3).plot(ax=axs[2, 1], alpha=0.6)
axs[2, 1].set_title("s.buffer(0.2, join_style=3)")
+28 -11
View File
@@ -1,17 +1,34 @@
/*This ensures that clickable links in the SG examples are the right color*/
div.section a span {
color: #2980B9 !important
/* colors */
:root {
--pst-color-primary: 19, 156, 90;
--pst-color-active-navigation: 19, 156, 90;
--pst-color-h2: var(--color-text-base);
}
/*Copied from sphinx' basic.css to ensure the sphinx >2.0 docstrings are
rendered somewhat properly (xref https://github.com/numpy/numpydoc/issues/215) */
/* buttons */
.classifier {
font-style: oblique;
.button>p>a {
box-shadow: 0px 4px 14px -7px #999999;
background-color: white;
border: 1px solid #bbbbbb;
display: inline-block;
cursor: pointer;
color: #139C5A;
padding: 1em 1em;
text-align: center;
text-decoration: none;
font-size: 140%;
margin: 2%;
width: 40%;
}
.classifier:before {
font-style: normal;
margin: 0.5em;
content: ":";
.button>p>a:hover {
border-color: #139C5A;
color: #e32e00;
}
.button>p>a:active {
position: relative;
top: 1px;
}
+202
View File
@@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 1531 629" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-miterlimit:10;">
<g transform="matrix(1,0,0,1,-65.3935,-1793.3)">
<g id="Artboard1" transform="matrix(0.799349,0,0,0.6338,71.418,752.489)">
<rect x="-7.537" y="1642.17" width="1915.21" height="991.964" style="fill:none;"/>
<g transform="matrix(5.21258,0,0,6.5741,242.724,1626.89)">
<g transform="matrix(12,0,0,12,6.3135,144.35)">
<path d="M0.089,-0.1L0.287,-0.1L0.287,-0.451L0.114,-0.451L0.114,-0.55L0.394,-0.55L0.394,-0.1L0.555,-0.1L0.555,-0L0.089,-0L0.089,-0.1ZM0.247,-0.701C0.247,-0.72 0.253,-0.736 0.266,-0.748C0.278,-0.759 0.294,-0.765 0.315,-0.765L0.339,-0.765C0.36,-0.765 0.376,-0.759 0.389,-0.748C0.401,-0.736 0.407,-0.72 0.407,-0.701C0.407,-0.682 0.401,-0.666 0.389,-0.655C0.376,-0.644 0.359,-0.638 0.338,-0.638L0.315,-0.638C0.294,-0.638 0.278,-0.644 0.266,-0.655C0.253,-0.666 0.247,-0.682 0.247,-0.701Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,13.5135,144.35)">
<path d="M0.079,-0.55L0.183,-0.55L0.183,-0.455L0.192,-0.455C0.199,-0.489 0.216,-0.515 0.241,-0.533C0.266,-0.551 0.299,-0.56 0.339,-0.56C0.368,-0.56 0.393,-0.555 0.416,-0.546C0.438,-0.536 0.457,-0.522 0.473,-0.505C0.488,-0.488 0.5,-0.467 0.508,-0.443C0.516,-0.418 0.52,-0.391 0.52,-0.362L0.52,-0L0.41,-0L0.41,-0.347C0.41,-0.385 0.4,-0.414 0.381,-0.435C0.362,-0.456 0.335,-0.466 0.301,-0.466C0.266,-0.466 0.239,-0.455 0.219,-0.433C0.199,-0.411 0.189,-0.381 0.189,-0.343L0.189,-0L0.079,-0L0.079,-0.55Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,20.7135,144.35)">
<path d="M0.069,-0.345C0.069,-0.378 0.074,-0.408 0.083,-0.435C0.092,-0.461 0.104,-0.483 0.121,-0.502C0.137,-0.521 0.157,-0.535 0.18,-0.545C0.203,-0.555 0.229,-0.56 0.257,-0.56C0.297,-0.56 0.33,-0.551 0.357,-0.533C0.383,-0.514 0.4,-0.488 0.407,-0.455L0.416,-0.455C0.415,-0.466 0.415,-0.478 0.414,-0.489C0.413,-0.499 0.412,-0.509 0.412,-0.521C0.411,-0.532 0.411,-0.541 0.411,-0.55L0.411,-0.72L0.52,-0.72L0.52,-0L0.416,-0L0.416,-0.095L0.407,-0.095C0.4,-0.062 0.383,-0.036 0.357,-0.018C0.33,0.001 0.297,0.01 0.257,0.01C0.229,0.01 0.203,0.005 0.18,-0.005C0.157,-0.015 0.137,-0.029 0.121,-0.048C0.104,-0.067 0.092,-0.09 0.083,-0.117C0.074,-0.143 0.069,-0.174 0.069,-0.207L0.069,-0.345ZM0.179,-0.343L0.179,-0.208C0.179,-0.171 0.19,-0.141 0.211,-0.119C0.232,-0.097 0.26,-0.086 0.297,-0.086C0.332,-0.086 0.359,-0.097 0.38,-0.119C0.401,-0.141 0.411,-0.17 0.411,-0.207L0.411,-0.343C0.411,-0.38 0.401,-0.41 0.38,-0.432C0.359,-0.454 0.331,-0.465 0.297,-0.465C0.26,-0.465 0.232,-0.454 0.211,-0.433C0.19,-0.411 0.179,-0.381 0.179,-0.343Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,27.9135,144.35)">
<path d="M0.069,-0.347C0.069,-0.38 0.074,-0.409 0.085,-0.436C0.096,-0.462 0.111,-0.484 0.131,-0.503C0.151,-0.521 0.175,-0.535 0.204,-0.545C0.233,-0.555 0.265,-0.56 0.3,-0.56C0.335,-0.56 0.367,-0.555 0.396,-0.545C0.424,-0.535 0.448,-0.521 0.468,-0.503C0.488,-0.484 0.503,-0.462 0.514,-0.436C0.525,-0.409 0.53,-0.38 0.53,-0.347L0.53,-0.246L0.178,-0.246L0.178,-0.207C0.178,-0.168 0.189,-0.137 0.211,-0.115C0.232,-0.093 0.262,-0.082 0.3,-0.082C0.328,-0.082 0.352,-0.086 0.373,-0.095C0.394,-0.104 0.409,-0.117 0.418,-0.134L0.526,-0.134C0.52,-0.112 0.51,-0.092 0.497,-0.075C0.484,-0.057 0.467,-0.042 0.448,-0.029C0.428,-0.016 0.405,-0.007 0.381,-0C0.356,0.007 0.329,0.01 0.3,0.01C0.265,0.01 0.233,0.005 0.205,-0.005C0.176,-0.015 0.152,-0.029 0.132,-0.048C0.112,-0.067 0.097,-0.089 0.086,-0.116C0.075,-0.142 0.069,-0.171 0.069,-0.204L0.069,-0.347ZM0.178,-0.326L0.422,-0.326L0.422,-0.347C0.422,-0.385 0.411,-0.415 0.39,-0.436C0.369,-0.457 0.339,-0.468 0.3,-0.468C0.261,-0.468 0.231,-0.457 0.21,-0.436C0.189,-0.415 0.178,-0.385 0.178,-0.347L0.178,-0.326Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,35.1135,144.35)">
<path d="M0.237,-0.283L0.051,-0.55L0.179,-0.55L0.281,-0.395C0.287,-0.387 0.291,-0.379 0.294,-0.37C0.296,-0.366 0.297,-0.362 0.298,-0.359L0.303,-0.359C0.304,-0.362 0.305,-0.366 0.307,-0.37C0.309,-0.377 0.313,-0.385 0.32,-0.395L0.423,-0.55L0.549,-0.55L0.364,-0.284L0.561,-0L0.433,-0L0.322,-0.169C0.319,-0.174 0.316,-0.178 0.314,-0.183C0.311,-0.188 0.309,-0.192 0.308,-0.195C0.306,-0.199 0.304,-0.203 0.303,-0.207L0.297,-0.207C0.296,-0.203 0.294,-0.199 0.292,-0.194C0.291,-0.191 0.289,-0.187 0.287,-0.183C0.285,-0.178 0.282,-0.174 0.279,-0.169L0.166,-0L0.039,-0L0.237,-0.283Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
</g>
<g transform="matrix(5.21258,0,0,6.5741,511.19,1626.9)">
<g transform="matrix(12,0,0,12,60.8892,144.35)">
<path d="M0.069,-0.345C0.069,-0.378 0.074,-0.408 0.083,-0.435C0.092,-0.461 0.104,-0.483 0.121,-0.502C0.137,-0.521 0.157,-0.535 0.18,-0.545C0.203,-0.555 0.229,-0.56 0.257,-0.56C0.297,-0.56 0.33,-0.551 0.357,-0.533C0.383,-0.514 0.4,-0.488 0.407,-0.455L0.416,-0.455C0.415,-0.466 0.415,-0.478 0.414,-0.489C0.413,-0.499 0.412,-0.509 0.412,-0.521C0.411,-0.532 0.411,-0.541 0.411,-0.55L0.411,-0.72L0.52,-0.72L0.52,-0L0.416,-0L0.416,-0.095L0.407,-0.095C0.4,-0.062 0.383,-0.036 0.357,-0.018C0.33,0.001 0.297,0.01 0.257,0.01C0.229,0.01 0.203,0.005 0.18,-0.005C0.157,-0.015 0.137,-0.029 0.121,-0.048C0.104,-0.067 0.092,-0.09 0.083,-0.117C0.074,-0.143 0.069,-0.174 0.069,-0.207L0.069,-0.345ZM0.179,-0.343L0.179,-0.208C0.179,-0.171 0.19,-0.141 0.211,-0.119C0.232,-0.097 0.26,-0.086 0.297,-0.086C0.332,-0.086 0.359,-0.097 0.38,-0.119C0.401,-0.141 0.411,-0.17 0.411,-0.207L0.411,-0.343C0.411,-0.38 0.401,-0.41 0.38,-0.432C0.359,-0.454 0.331,-0.465 0.297,-0.465C0.26,-0.465 0.232,-0.454 0.211,-0.433C0.19,-0.411 0.179,-0.381 0.179,-0.343Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,68.0892,144.35)">
<path d="M0.056,-0.157C0.056,-0.21 0.075,-0.253 0.112,-0.284C0.149,-0.315 0.199,-0.331 0.262,-0.331L0.411,-0.331L0.411,-0.377C0.411,-0.406 0.401,-0.429 0.381,-0.446C0.36,-0.462 0.331,-0.47 0.294,-0.47C0.265,-0.47 0.241,-0.465 0.221,-0.455C0.201,-0.444 0.188,-0.43 0.181,-0.411L0.073,-0.411C0.082,-0.457 0.106,-0.493 0.146,-0.52C0.186,-0.547 0.236,-0.56 0.295,-0.56C0.365,-0.56 0.42,-0.544 0.461,-0.512C0.501,-0.48 0.521,-0.436 0.521,-0.38L0.521,-0L0.419,-0L0.419,-0.107L0.411,-0.107C0.404,-0.071 0.384,-0.043 0.353,-0.022C0.321,-0.001 0.282,0.01 0.235,0.01C0.18,0.01 0.137,-0.005 0.105,-0.036C0.072,-0.066 0.056,-0.106 0.056,-0.157ZM0.166,-0.166C0.166,-0.138 0.175,-0.116 0.193,-0.101C0.211,-0.086 0.236,-0.078 0.269,-0.078C0.29,-0.078 0.309,-0.081 0.326,-0.086C0.343,-0.091 0.358,-0.099 0.371,-0.109C0.384,-0.118 0.394,-0.13 0.401,-0.143C0.408,-0.156 0.411,-0.17 0.411,-0.185L0.411,-0.254L0.263,-0.254C0.233,-0.254 0.209,-0.246 0.192,-0.231C0.175,-0.216 0.166,-0.194 0.166,-0.166Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,75.2892,144.35)">
<path d="M0.052,-0.55L0.207,-0.55L0.207,-0.72L0.317,-0.72L0.317,-0.55L0.528,-0.55L0.528,-0.451L0.317,-0.451L0.317,-0.158C0.317,-0.14 0.322,-0.126 0.333,-0.116C0.344,-0.105 0.359,-0.1 0.378,-0.1L0.518,-0.1L0.518,-0L0.373,-0C0.322,-0 0.281,-0.014 0.252,-0.043C0.222,-0.072 0.207,-0.11 0.207,-0.158L0.207,-0.451L0.052,-0.451L0.052,-0.55Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,82.4892,144.35)">
<path d="M0.056,-0.157C0.056,-0.21 0.075,-0.253 0.112,-0.284C0.149,-0.315 0.199,-0.331 0.262,-0.331L0.411,-0.331L0.411,-0.377C0.411,-0.406 0.401,-0.429 0.381,-0.446C0.36,-0.462 0.331,-0.47 0.294,-0.47C0.265,-0.47 0.241,-0.465 0.221,-0.455C0.201,-0.444 0.188,-0.43 0.181,-0.411L0.073,-0.411C0.082,-0.457 0.106,-0.493 0.146,-0.52C0.186,-0.547 0.236,-0.56 0.295,-0.56C0.365,-0.56 0.42,-0.544 0.461,-0.512C0.501,-0.48 0.521,-0.436 0.521,-0.38L0.521,-0L0.419,-0L0.419,-0.107L0.411,-0.107C0.404,-0.071 0.384,-0.043 0.353,-0.022C0.321,-0.001 0.282,0.01 0.235,0.01C0.18,0.01 0.137,-0.005 0.105,-0.036C0.072,-0.066 0.056,-0.106 0.056,-0.157ZM0.166,-0.166C0.166,-0.138 0.175,-0.116 0.193,-0.101C0.211,-0.086 0.236,-0.078 0.269,-0.078C0.29,-0.078 0.309,-0.081 0.326,-0.086C0.343,-0.091 0.358,-0.099 0.371,-0.109C0.384,-0.118 0.394,-0.13 0.401,-0.143C0.408,-0.156 0.411,-0.17 0.411,-0.185L0.411,-0.254L0.263,-0.254C0.233,-0.254 0.209,-0.246 0.192,-0.231C0.175,-0.216 0.166,-0.194 0.166,-0.166Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
</g>
<g transform="matrix(5.21258,0,0,6.5741,242.724,1632)">
<g opacity="0.2">
<g transform="matrix(-1,0,0,1,48.676,-90.177)">
<rect x="5.237" y="117.958" width="38.202" height="19.101" style="fill:rgb(15,157,90);stroke:white;stroke-width:1px;"/>
</g>
</g>
</g>
<g transform="matrix(5.21258,0,0,6.5741,242.724,1632)">
<g opacity="0.4">
<g transform="matrix(-1,0,0,1,48.676,-51.975)">
<rect x="5.237" y="98.857" width="38.202" height="19.101" style="fill:rgb(15,157,90);stroke:white;stroke-width:1px;"/>
</g>
</g>
</g>
<g transform="matrix(5.21258,0,0,6.5741,242.724,1632)">
<g opacity="0.6">
<g transform="matrix(-1,0,0,1,48.676,-13.771)">
<rect x="5.237" y="79.755" width="38.202" height="19.101" style="fill:rgb(15,157,90);stroke:white;stroke-width:1px;"/>
</g>
</g>
</g>
<g transform="matrix(5.21258,0,0,6.5741,242.724,1632)">
<g opacity="0.8">
<g transform="matrix(-1,0,0,1,48.676,24.431)">
<rect x="5.237" y="60.654" width="38.202" height="19.101" style="fill:rgb(15,157,90);stroke:white;stroke-width:1px;"/>
</g>
</g>
</g>
<g transform="matrix(-5.21258,0,0,6.5741,496.451,2043.75)">
<rect x="5.237" y="41.553" width="38.202" height="19.101" style="fill:rgb(15,157,90);stroke:white;stroke-width:1px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,912.853,1039.17)">
<rect x="48.041" y="117.958" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1188.41,1039.17)">
<rect x="48.041" y="117.958" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1464.92,1039.17)">
<rect x="48.041" y="117.958" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,912.853,788.023)">
<rect x="48.041" y="137.059" width="83.409" height="19.101" style="fill:rgb(255,211,85);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1188.41,788.023)">
<rect x="48.041" y="137.059" width="83.409" height="19.101" style="fill:rgb(255,211,85);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1464.92,788.023)">
<rect x="48.041" y="137.059" width="83.409" height="19.101" style="fill:rgb(255,211,85);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,912.853,1290.31)">
<rect x="48.041" y="98.857" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1188.41,1290.31)">
<rect x="48.041" y="98.857" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1464.92,1290.31)">
<rect x="48.041" y="98.857" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,912.853,1541.47)">
<rect x="48.041" y="79.755" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1188.41,1541.47)">
<rect x="48.041" y="79.755" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1464.92,1541.47)">
<rect x="48.041" y="79.755" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,912.853,1792.61)">
<rect x="48.041" y="60.654" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1188.41,1792.61)">
<rect x="48.041" y="60.654" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1464.92,1792.61)">
<rect x="48.041" y="60.654" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,912.853,2043.75)">
<rect x="48.041" y="41.553" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1188.41,2043.75)">
<rect x="48.041" y="41.553" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-3.15195,0,0,6.5741,1464.92,2043.75)">
<rect x="48.041" y="41.553" width="83.409" height="19.101" style="fill:rgb(255,238,196);stroke:white;stroke-width:1.21px;"/>
</g>
<g transform="matrix(-5.21258,0,0,6.5741,496.196,1539.33)">
<rect x="3.188" y="39.493" width="42.251" height="99.95" style="fill:none;stroke:rgb(29,29,27);stroke-width:0.5px;"/>
</g>
<g transform="matrix(-9.67868,0,0,6.5741,1773.61,1413.32)">
<rect x="46.279" y="39.493" width="86.813" height="119.117" style="fill:none;stroke:rgb(29,29,27);stroke-width:0.34px;"/>
</g>
<g transform="matrix(-3.39963,0,0,6.5741,1784.48,1413.32)">
<rect x="46.279" y="39.493" width="86.813" height="119.117" style="fill:none;stroke:rgb(29,29,27);stroke-width:0.59px;"/>
</g>
<g transform="matrix(3.12731,0,0,6.5741,608.309,1635.41)">
<g opacity="0.2">
<g transform="matrix(-1,0,0,1,557.99,-90.177)">
<rect x="237.291" y="117.958" width="83.408" height="19.101" style="fill:rgb(226,28,132);stroke:white;stroke-width:1.21px;"/>
</g>
</g>
</g>
<g transform="matrix(3.12731,0,0,6.5741,608.309,1635.41)">
<g opacity="0.4">
<g transform="matrix(-1,0,0,1,557.99,-128.379)">
<rect x="237.291" y="137.059" width="83.408" height="19.101" style="fill:rgb(226,28,132);stroke:white;stroke-width:1.21px;"/>
</g>
</g>
</g>
<g transform="matrix(3.12731,0,0,6.5741,608.309,1635.41)">
<g opacity="0.2">
<g transform="matrix(-1,0,0,1,557.99,-51.975)">
<rect x="237.291" y="98.857" width="83.408" height="19.101" style="fill:rgb(226,28,132);stroke:white;stroke-width:1.21px;"/>
</g>
</g>
</g>
<g transform="matrix(3.12731,0,0,6.5741,608.309,1635.41)">
<g opacity="0.2">
<g transform="matrix(-1,0,0,1,557.99,-13.771)">
<rect x="237.291" y="79.755" width="83.408" height="19.101" style="fill:rgb(226,28,132);stroke:white;stroke-width:1.21px;"/>
</g>
</g>
</g>
<g transform="matrix(3.12731,0,0,6.5741,608.309,1635.41)">
<g opacity="0.2">
<g transform="matrix(-1,0,0,1,557.99,24.431)">
<rect x="237.291" y="60.654" width="83.408" height="19.101" style="fill:rgb(226,28,132);stroke:white;stroke-width:1.21px;"/>
</g>
</g>
</g>
<g transform="matrix(3.12731,0,0,6.5741,608.309,1635.41)">
<g opacity="0.2">
<g transform="matrix(-1,0,0,1,557.99,62.633)">
<rect x="237.291" y="41.553" width="83.408" height="19.101" style="fill:rgb(226,28,132);stroke:white;stroke-width:1.21px;"/>
</g>
</g>
</g>
<g transform="matrix(5.21258,0,0,6.5741,1013.41,1626.9)">
<g transform="matrix(12,0,0,12,60.8892,144.35)">
<path d="M0.065,-0.348C0.065,-0.38 0.069,-0.409 0.078,-0.436C0.087,-0.462 0.099,-0.484 0.116,-0.503C0.133,-0.521 0.153,-0.535 0.176,-0.545C0.199,-0.555 0.225,-0.56 0.254,-0.56C0.295,-0.56 0.329,-0.55 0.356,-0.531C0.383,-0.512 0.401,-0.485 0.409,-0.45L0.416,-0.45L0.416,-0.55L0.52,-0.55L0.52,-0.033C0.52,0.03 0.5,0.079 0.461,0.116C0.421,0.152 0.366,0.17 0.297,0.17L0.155,0.17L0.155,0.076L0.297,0.076C0.332,0.076 0.36,0.066 0.381,0.047C0.401,0.028 0.411,0.001 0.411,-0.033L0.411,-0.052L0.415,-0.152L0.409,-0.152C0.4,-0.117 0.382,-0.09 0.355,-0.071C0.328,-0.052 0.294,-0.042 0.253,-0.042C0.224,-0.042 0.199,-0.047 0.176,-0.057C0.153,-0.067 0.133,-0.081 0.117,-0.1C0.1,-0.118 0.088,-0.14 0.079,-0.166C0.07,-0.192 0.065,-0.221 0.065,-0.253L0.065,-0.348ZM0.176,-0.255C0.176,-0.218 0.187,-0.19 0.208,-0.169C0.229,-0.148 0.257,-0.137 0.293,-0.137C0.33,-0.137 0.359,-0.148 0.38,-0.169C0.401,-0.19 0.411,-0.218 0.411,-0.255L0.411,-0.347C0.411,-0.384 0.401,-0.413 0.38,-0.434C0.359,-0.455 0.33,-0.465 0.293,-0.465C0.257,-0.465 0.229,-0.455 0.208,-0.434C0.187,-0.413 0.176,-0.384 0.176,-0.347L0.176,-0.255Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,68.0892,144.35)">
<path d="M0.069,-0.347C0.069,-0.38 0.074,-0.409 0.085,-0.436C0.096,-0.462 0.111,-0.484 0.131,-0.503C0.151,-0.521 0.175,-0.535 0.204,-0.545C0.233,-0.555 0.265,-0.56 0.3,-0.56C0.335,-0.56 0.367,-0.555 0.396,-0.545C0.424,-0.535 0.448,-0.521 0.468,-0.503C0.488,-0.484 0.503,-0.462 0.514,-0.436C0.525,-0.409 0.53,-0.38 0.53,-0.347L0.53,-0.246L0.178,-0.246L0.178,-0.207C0.178,-0.168 0.189,-0.137 0.211,-0.115C0.232,-0.093 0.262,-0.082 0.3,-0.082C0.328,-0.082 0.352,-0.086 0.373,-0.095C0.394,-0.104 0.409,-0.117 0.418,-0.134L0.526,-0.134C0.52,-0.112 0.51,-0.092 0.497,-0.075C0.484,-0.057 0.467,-0.042 0.448,-0.029C0.428,-0.016 0.405,-0.007 0.381,-0C0.356,0.007 0.329,0.01 0.3,0.01C0.265,0.01 0.233,0.005 0.205,-0.005C0.176,-0.015 0.152,-0.029 0.132,-0.048C0.112,-0.067 0.097,-0.089 0.086,-0.116C0.075,-0.142 0.069,-0.171 0.069,-0.204L0.069,-0.347ZM0.178,-0.326L0.422,-0.326L0.422,-0.347C0.422,-0.385 0.411,-0.415 0.39,-0.436C0.369,-0.457 0.339,-0.468 0.3,-0.468C0.261,-0.468 0.231,-0.457 0.21,-0.436C0.189,-0.415 0.178,-0.385 0.178,-0.347L0.178,-0.326Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,75.2892,144.35)">
<path d="M0.3,0.01C0.265,0.01 0.233,0.005 0.205,-0.006C0.176,-0.016 0.152,-0.031 0.132,-0.05C0.112,-0.069 0.097,-0.091 0.086,-0.118C0.075,-0.145 0.069,-0.174 0.069,-0.207L0.069,-0.344C0.069,-0.377 0.075,-0.406 0.086,-0.433C0.097,-0.46 0.112,-0.483 0.132,-0.502C0.152,-0.521 0.176,-0.535 0.205,-0.546C0.233,-0.556 0.265,-0.561 0.3,-0.561C0.335,-0.561 0.367,-0.556 0.396,-0.546C0.424,-0.536 0.448,-0.522 0.468,-0.503C0.488,-0.484 0.503,-0.461 0.515,-0.435C0.526,-0.408 0.531,-0.378 0.531,-0.345L0.531,-0.207C0.531,-0.174 0.526,-0.145 0.515,-0.118C0.504,-0.091 0.489,-0.068 0.469,-0.049C0.449,-0.03 0.425,-0.016 0.396,-0.006C0.367,0.005 0.335,0.01 0.3,0.01ZM0.179,-0.207C0.179,-0.17 0.19,-0.14 0.211,-0.119C0.232,-0.098 0.262,-0.087 0.3,-0.087C0.337,-0.087 0.367,-0.098 0.389,-0.119C0.41,-0.14 0.421,-0.17 0.421,-0.207L0.421,-0.344C0.421,-0.381 0.41,-0.411 0.389,-0.432C0.367,-0.453 0.337,-0.464 0.3,-0.464C0.263,-0.464 0.233,-0.453 0.212,-0.432C0.19,-0.411 0.179,-0.381 0.179,-0.344L0.179,-0.207Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,82.4892,144.35)">
<path d="M0.055,-0L0.055,-0.55L0.146,-0.55L0.146,-0.469L0.154,-0.469C0.156,-0.498 0.165,-0.52 0.181,-0.536C0.196,-0.552 0.217,-0.56 0.244,-0.56C0.269,-0.56 0.289,-0.552 0.304,-0.537C0.319,-0.522 0.329,-0.499 0.336,-0.469L0.343,-0.469C0.345,-0.498 0.354,-0.52 0.37,-0.536C0.386,-0.552 0.408,-0.56 0.435,-0.56C0.468,-0.56 0.495,-0.548 0.516,-0.523C0.536,-0.498 0.546,-0.463 0.546,-0.419L0.546,-0L0.445,-0L0.445,-0.414C0.445,-0.435 0.441,-0.452 0.432,-0.463C0.423,-0.474 0.411,-0.48 0.394,-0.48C0.359,-0.48 0.341,-0.457 0.341,-0.41L0.341,-0L0.26,-0L0.26,-0.414C0.26,-0.435 0.255,-0.452 0.246,-0.463C0.237,-0.474 0.223,-0.48 0.206,-0.48C0.171,-0.48 0.154,-0.457 0.154,-0.41L0.154,-0L0.055,-0Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,89.6892,144.35)">
<path d="M0.069,-0.347C0.069,-0.38 0.074,-0.409 0.085,-0.436C0.096,-0.462 0.111,-0.484 0.131,-0.503C0.151,-0.521 0.175,-0.535 0.204,-0.545C0.233,-0.555 0.265,-0.56 0.3,-0.56C0.335,-0.56 0.367,-0.555 0.396,-0.545C0.424,-0.535 0.448,-0.521 0.468,-0.503C0.488,-0.484 0.503,-0.462 0.514,-0.436C0.525,-0.409 0.53,-0.38 0.53,-0.347L0.53,-0.246L0.178,-0.246L0.178,-0.207C0.178,-0.168 0.189,-0.137 0.211,-0.115C0.232,-0.093 0.262,-0.082 0.3,-0.082C0.328,-0.082 0.352,-0.086 0.373,-0.095C0.394,-0.104 0.409,-0.117 0.418,-0.134L0.526,-0.134C0.52,-0.112 0.51,-0.092 0.497,-0.075C0.484,-0.057 0.467,-0.042 0.448,-0.029C0.428,-0.016 0.405,-0.007 0.381,-0C0.356,0.007 0.329,0.01 0.3,0.01C0.265,0.01 0.233,0.005 0.205,-0.005C0.176,-0.015 0.152,-0.029 0.132,-0.048C0.112,-0.067 0.097,-0.089 0.086,-0.116C0.075,-0.142 0.069,-0.171 0.069,-0.204L0.069,-0.347ZM0.178,-0.326L0.422,-0.326L0.422,-0.347C0.422,-0.385 0.411,-0.415 0.39,-0.436C0.369,-0.457 0.339,-0.468 0.3,-0.468C0.261,-0.468 0.231,-0.457 0.21,-0.436C0.189,-0.415 0.178,-0.385 0.178,-0.347L0.178,-0.326Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,96.8892,144.35)">
<path d="M0.052,-0.55L0.207,-0.55L0.207,-0.72L0.317,-0.72L0.317,-0.55L0.528,-0.55L0.528,-0.451L0.317,-0.451L0.317,-0.158C0.317,-0.14 0.322,-0.126 0.333,-0.116C0.344,-0.105 0.359,-0.1 0.378,-0.1L0.518,-0.1L0.518,-0L0.373,-0C0.322,-0 0.281,-0.014 0.252,-0.043C0.222,-0.072 0.207,-0.11 0.207,-0.158L0.207,-0.451L0.052,-0.451L0.052,-0.55Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,104.089,144.35)">
<path d="M0.206,-0.55L0.206,-0.455L0.215,-0.455C0.222,-0.488 0.24,-0.514 0.267,-0.533C0.294,-0.551 0.327,-0.56 0.368,-0.56C0.427,-0.56 0.473,-0.542 0.506,-0.506C0.539,-0.469 0.556,-0.419 0.556,-0.354L0.556,-0.318L0.443,-0.318L0.443,-0.343C0.443,-0.382 0.433,-0.412 0.412,-0.434C0.391,-0.455 0.363,-0.466 0.327,-0.466C0.292,-0.466 0.264,-0.455 0.243,-0.433C0.222,-0.411 0.212,-0.381 0.212,-0.343L0.212,-0L0.102,-0L0.102,-0.55L0.206,-0.55Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
<g transform="matrix(12,0,0,12,111.289,144.35)">
<path d="M0.042,-0.55L0.162,-0.55L0.278,-0.247C0.283,-0.234 0.288,-0.221 0.291,-0.208C0.294,-0.195 0.296,-0.182 0.298,-0.171C0.3,-0.158 0.302,-0.146 0.303,-0.135L0.311,-0.135C0.312,-0.146 0.313,-0.158 0.315,-0.171C0.317,-0.182 0.32,-0.194 0.323,-0.207C0.326,-0.22 0.329,-0.234 0.334,-0.247L0.442,-0.55L0.558,-0.55L0.294,0.17L0.178,0.17L0.254,-0.035L0.042,-0.55Z" style="fill:rgb(29,29,27);fill-rule:nonzero;"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

@@ -0,0 +1 @@
<svg id="Vrstva_1" data-name="Vrstva 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 313.97 313.97"><defs><style>.cls-1{fill:#fec905;}.cls-2{fill:#e21c84;}.cls-3{fill:#0f9c5a;}</style></defs><rect class="cls-1" x="160.46" y="149.32" width="24.09" height="23.6"/><rect class="cls-2" x="198.36" y="190.51" width="24.09" height="23.6"/><rect class="cls-3" x="160.46" y="84.7" width="24.09" height="50.02"/><rect class="cls-3" x="160.46" y="187.45" width="24.09" height="50.02"/><rect class="cls-3" x="198.36" y="125.89" width="24.09" height="50.02"/><path class="cls-3" d="M156.34,19.69C80,19.69,17.89,81.8,17.89,158.14S80,296.6,156.34,296.6s138.45-62.11,138.45-138.46S232.68,19.69,156.34,19.69ZM269.79,158.14a112.88,112.88,0,0,1-9.45,45.32V112.82A112.92,112.92,0,0,1,269.79,158.14Zm-47.34,92.15V228.72H198.36v34.81a112.94,112.94,0,0,1-42,8.07c-3.54,0-7-.18-10.48-.49V125.83H121.77V266.2A113.44,113.44,0,1,1,236.25,77.68V237.94h.66A115.12,115.12,0,0,1,222.45,250.29Z"/></svg>

After

Width:  |  Height:  |  Size: 975 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

@@ -0,0 +1 @@
<svg id="Vrstva_1" data-name="Vrstva 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 313.97 313.97"><defs><style>.cls-1{fill:#0f9c5a;}.cls-2{fill:#fff;}.cls-3{fill:#fec905;}.cls-4{fill:#e21c84;}</style></defs><rect class="cls-1" width="313.97" height="313.97"/><rect class="cls-2" x="159.41" y="84.7" width="24.09" height="50.02"/><rect class="cls-2" x="159.41" y="187.45" width="24.09" height="50.02"/><rect class="cls-3" x="159.41" y="149.32" width="24.09" height="23.6"/><rect class="cls-2" x="197.31" y="125.89" width="24.09" height="50.02"/><rect class="cls-4" x="197.31" y="190.51" width="24.09" height="23.6"/><path class="cls-2" d="M155.29,19.69C79,19.69,16.84,81.8,16.84,158.14S79,296.6,155.29,296.6s138.46-62.11,138.46-138.46S231.64,19.69,155.29,19.69ZM268.75,158.14a112.72,112.72,0,0,1-9.46,45.32V112.82A112.75,112.75,0,0,1,268.75,158.14ZM221.4,250.29V228.72H197.31v34.81a112.9,112.9,0,0,1-42,8.07c-3.53,0-7-.18-10.48-.49V125.83H120.72V266.2A113.44,113.44,0,1,1,235.2,77.68V237.94h.66A114.42,114.42,0,0,1,221.4,250.29Z"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

@@ -0,0 +1 @@
<svg id="Vrstva_1" data-name="Vrstva 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1324.25 412.98"><defs><style>.cls-1{fill:#fec905;}.cls-2{fill:#e21c84;}.cls-3{fill:#0f9c5a;}</style></defs><rect class="cls-1" x="211.63" y="198.82" width="24.09" height="23.6"/><rect class="cls-2" x="249.53" y="240.01" width="24.09" height="23.6"/><path class="cls-3" d="M471.5,267c-31.14,0-57.42-22.14-57.42-57.06s27.36-56.34,58.86-56.34c14.22,0,29.34,4.14,38.34,11v20c-9-7.56-20.16-13.32-36.18-13.32-22.5,0-38.16,14.76-38.16,39.6,0,24.3,15.3,39.6,36.9,39.6,8.28,0,15.3-1.62,20.88-4.5V224.9H475.64V208.7h40.14v47.7C509.66,258.92,492.74,267,471.5,267Z"/><path class="cls-3" d="M601.1,225.62H549.26c-.54,11.88,5.58,25.38,26.46,25.38,8.82,0,19.26-4,25.2-9.18v15.12c-7.38,5.76-18.72,9.18-31.68,9.18-23.94,0-40.68-17.46-40.68-41.58,0-24.84,19.08-40.5,39.24-40.5,19.8,0,34.56,12.42,34.56,30.78A49.41,49.41,0,0,1,601.1,225.62Zm-32.76-28.26c-8.82,0-16.38,5-18.18,17.1h33.3C585.26,205.1,579.14,197.36,568.34,197.36Z"/><path class="cls-3" d="M654.37,266.84c-25.19,0-43.73-18.18-43.73-41.76,0-23.4,18.54-41.76,43.73-41.76,25,0,43.56,18.36,43.56,41.76C697.93,248.66,679.39,266.84,654.37,266.84Zm0-68.22c-14,0-23.21,10.8-23.21,26.46,0,15.84,9.36,26.46,23.21,26.46s23-10.62,23-26.46C677.41,209.42,668.23,198.62,654.37,198.62Z"/><path class="cls-3" d="M751,224.72H732V264H710V156h41c25.92,0,37.44,15.84,37.44,34.38C788.47,209.06,777,224.72,751,224.72Zm-3.6-53.1H732v37.44h15.48c14.22,0,19.26-8.46,19.26-18.72C766.69,180.26,761.65,171.62,747.43,171.62Z"/><path class="cls-3" d="M858,264l-.72-12.42c-6.48,9.54-18,14.58-29,14.58-21,0-36.53-17.64-36.53-41s15.48-41,36.53-41c11,0,22.5,5,29,14.58L858,186.2h18.9V264Zm-23.22-64.44c-12.24,0-22.14,9.54-22.14,25.56s9.9,25.56,22.14,25.56,22.14-9.54,22.14-25.56S847,199.52,834.73,199.52Z"/><path class="cls-3" d="M949.57,264v-43c0-15.12-5.22-20.16-14.76-20.16-9.9,0-20.7,9-20.7,19.8V264H893.24V186.2h19.07l.9,14.4C918.43,190.7,930.13,184,942,184c20.7,0,28.44,14.4,28.44,33.66V264Z"/><path class="cls-3" d="M1048.39,264l-.72-12.42c-6.48,9.54-18,14.58-29,14.58-21.06,0-36.54-17.64-36.54-41s15.48-41,36.54-41c10.44,0,21.06,4.32,27.72,12.78V156h20.88V264Zm-23.22-64.44c-12.24,0-22.14,9.54-22.14,25.56s9.9,25.56,22.14,25.56,22.14-9.54,22.14-25.56S1037.41,199.52,1025.17,199.52Z"/><path class="cls-3" d="M1145.41,264l-.72-12.42c-6.48,9.54-18,14.58-29,14.58-21.06,0-36.54-17.64-36.54-41s15.48-41,36.54-41c11,0,22.5,5,29,14.58l.72-12.42h18.9V264Zm-23.22-64.44c-12.24,0-22.14,9.54-22.14,25.56s9.9,25.56,22.14,25.56,22.14-9.54,22.14-25.56S1134.43,199.52,1122.19,199.52Z"/><path class="cls-3" d="M1206.43,266.48a61.17,61.17,0,0,1-31.14-8.82l3.42-14.4c6.3,3.78,15.84,8.64,27.36,8.64,8.28,0,14-2.52,14-9,0-5.58-5.94-7.56-16.56-10.08-19.08-4.14-25.92-14.22-25.92-25.2,0-12.24,9.54-23.76,30.6-23.76,12.78,0,23.94,5.58,26.46,7l-3.42,13.68a45.3,45.3,0,0,0-22.5-6.48c-8.46,0-12.6,2.88-12.6,7.56,0,5.22,5.4,7.56,13.68,9.54,20.52,4.32,28.8,13.86,28.8,24.3C1238.65,256.22,1226.41,266.48,1206.43,266.48Z"/><rect class="cls-3" x="211.63" y="134.2" width="24.09" height="50.02"/><rect class="cls-3" x="211.63" y="236.95" width="24.09" height="50.02"/><rect class="cls-3" x="249.53" y="175.39" width="24.09" height="50.02"/><path class="cls-3" d="M207.51,69.19c-76.34,0-138.45,62.11-138.45,138.45S131.17,346.1,207.51,346.1,346,284,346,207.64,283.85,69.19,207.51,69.19ZM321,207.64A112.84,112.84,0,0,1,311.51,253V162.32A112.92,112.92,0,0,1,321,207.64Zm-47.34,92.15V278.22H249.53V313a112.9,112.9,0,0,1-42,8.07c-3.53,0-7-.17-10.48-.49V175.33H172.94V315.7A113.44,113.44,0,1,1,287.42,127.19V287.44h.66A114.42,114.42,0,0,1,273.62,299.79Z"/></svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

@@ -0,0 +1 @@
<svg id="Vrstva_1" data-name="Vrstva 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1324.25 412.98"><defs><style>.cls-1{fill:#0f9c5a;}.cls-2{fill:#fff;}.cls-3{fill:#fec905;}.cls-4{fill:#e21c84;}</style></defs><rect class="cls-1" width="1324.25" height="412.98"/><path class="cls-2" d="M484.46,267c-31.13,0-57.41-22.14-57.41-57.06s27.36-56.34,58.85-56.34c14.22,0,29.34,4.14,38.34,11v20c-9-7.56-20.16-13.32-36.18-13.32-22.5,0-38.15,14.76-38.15,39.6,0,24.3,15.29,39.6,36.89,39.6,8.28,0,15.3-1.62,20.88-4.5V224.9H488.6V208.7h40.14v47.7C522.62,258.92,505.7,267,484.46,267Z"/><path class="cls-2" d="M614.06,225.62H562.22C561.68,237.5,567.8,251,588.68,251c8.82,0,19.26-4,25.2-9.18v15.12c-7.38,5.76-18.72,9.18-31.68,9.18-23.94,0-40.68-17.46-40.68-41.58,0-24.84,19.08-40.5,39.24-40.5,19.8,0,34.56,12.42,34.56,30.78A49.41,49.41,0,0,1,614.06,225.62ZM581.3,197.36c-8.82,0-16.38,5-18.18,17.1h33.3C598.22,205.1,592.1,197.36,581.3,197.36Z"/><path class="cls-2" d="M667.34,266.84c-25.2,0-43.74-18.18-43.74-41.76,0-23.4,18.54-41.76,43.74-41.76,25,0,43.56,18.36,43.56,41.76C710.9,248.66,692.36,266.84,667.34,266.84Zm0-68.22c-14,0-23.22,10.8-23.22,26.46,0,15.84,9.36,26.46,23.22,26.46s23-10.62,23-26.46C690.38,209.42,681.2,198.62,667.34,198.62Z"/><path class="cls-2" d="M764,224.72H744.92V264H723V156h41c25.92,0,37.44,15.84,37.44,34.38C801.44,209.06,789.92,224.72,764,224.72Zm-3.6-53.1H744.92v37.44H760.4c14.22,0,19.26-8.46,19.26-18.72C779.66,180.26,774.62,171.62,760.4,171.62Z"/><path class="cls-2" d="M870.92,264l-.72-12.42c-6.48,9.54-18,14.58-29,14.58-21.06,0-36.54-17.64-36.54-41s15.48-41,36.54-41c11,0,22.5,5,29,14.58l.72-12.42h18.9V264ZM847.7,199.52c-12.24,0-22.14,9.54-22.14,25.56s9.9,25.56,22.14,25.56,22.14-9.54,22.14-25.56S859.94,199.52,847.7,199.52Z"/><path class="cls-2" d="M962.54,264v-43c0-15.12-5.22-20.16-14.76-20.16-9.9,0-20.7,9-20.7,19.8V264H906.2V186.2h19.08l.9,14.4C931.4,190.7,943.1,184,955,184c20.7,0,28.44,14.4,28.44,33.66V264Z"/><path class="cls-2" d="M1061.36,264l-.72-12.42c-6.48,9.54-18,14.58-29,14.58-21.06,0-36.54-17.64-36.54-41s15.48-41,36.54-41c10.44,0,21.06,4.32,27.72,12.78V156h20.88V264Zm-23.22-64.44c-12.24,0-22.14,9.54-22.14,25.56s9.9,25.56,22.14,25.56,22.14-9.54,22.14-25.56S1050.38,199.52,1038.14,199.52Z"/><path class="cls-2" d="M1158.38,264l-.72-12.42c-6.48,9.54-18,14.58-29,14.58-21.06,0-36.54-17.64-36.54-41s15.48-41,36.54-41c11,0,22.5,5,29,14.58l.72-12.42h18.89V264Zm-23.22-64.44c-12.24,0-22.14,9.54-22.14,25.56s9.9,25.56,22.14,25.56,22.14-9.54,22.14-25.56S1147.4,199.52,1135.16,199.52Z"/><path class="cls-2" d="M1219.4,266.48a61.17,61.17,0,0,1-31.14-8.82l3.42-14.4c6.3,3.78,15.84,8.64,27.36,8.64,8.28,0,14-2.52,14-9,0-5.58-5.94-7.56-16.56-10.08-19.08-4.14-25.92-14.22-25.92-25.2,0-12.24,9.54-23.76,30.6-23.76,12.78,0,23.93,5.58,26.46,7l-3.42,13.68a45.3,45.3,0,0,0-22.5-6.48c-8.46,0-12.6,2.88-12.6,7.56,0,5.22,5.4,7.56,13.68,9.54,20.52,4.32,28.79,13.86,28.79,24.3C1251.61,256.22,1239.38,266.48,1219.4,266.48Z"/><rect class="cls-2" x="224.59" y="134.2" width="24.09" height="50.02"/><rect class="cls-2" x="224.59" y="236.95" width="24.09" height="50.02"/><rect class="cls-3" x="224.59" y="198.82" width="24.09" height="23.6"/><rect class="cls-2" x="262.49" y="175.39" width="24.09" height="50.02"/><rect class="cls-4" x="262.49" y="240.01" width="24.09" height="23.6"/><path class="cls-2" d="M220.48,69.19C144.13,69.19,82,131.3,82,207.64S144.13,346.1,220.48,346.1,358.93,284,358.93,207.64,296.82,69.19,220.48,69.19ZM333.93,207.64A112.68,112.68,0,0,1,324.47,253V162.32A112.75,112.75,0,0,1,333.93,207.64Zm-47.35,92.15V278.22H262.49V313a112.89,112.89,0,0,1-42,8.07c-3.54,0-7-.17-10.49-.49V175.33H185.9V315.7A113.44,113.44,0,1,1,300.38,127.19V287.44h.67A115.21,115.21,0,0,1,286.58,299.79Z"/></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1393.8 292.8" style="enable-background:new 0 0 1393.8 292.8;" xml:space="preserve">
<style type="text/css">
.st0{fill:#130754;}
.st1{fill:#139C5A;}
.st2{fill:#04542F;}
.st3{fill:#166799;}
.st4{fill:#FFCA00;}
.st5{fill:#E70488;}
.st6{fill:#FFFFFF;stroke:#9C9C9C;stroke-width:0.75;stroke-miterlimit:10;}
.st7{fill:#FFFFFF;}
</style>
<g id="Layer_7">
</g>
<g id="Layer_1">
</g>
<g id="Layer_6">
</g>
<g id="Layer_2">
</g>
<g id="Layer_5">
<rect x="243.2" y="137.8" class="st4" width="24.1" height="23.6"/>
<rect x="281.1" y="179" class="st5" width="24.1" height="23.6"/>
<g>
<path class="st1" d="M503,206c-31.1,0-57.4-22.1-57.4-57.1c0-34.9,27.4-56.3,58.9-56.3c14.2,0,29.3,4.1,38.3,11v20
c-9-7.6-20.2-13.3-36.2-13.3c-22.5,0-38.2,14.8-38.2,39.6c0,24.3,15.3,39.6,36.9,39.6c8.3,0,15.3-1.6,20.9-4.5v-21.1h-19.1v-16.2
h40.1v47.7C541.2,197.9,524.3,206,503,206z"/>
<path class="st1" d="M632.6,164.6h-51.8c-0.5,11.9,5.6,25.4,26.5,25.4c8.8,0,19.3-4,25.2-9.2V196c-7.4,5.8-18.7,9.2-31.7,9.2
c-23.9,0-40.7-17.5-40.7-41.6c0-24.8,19.1-40.5,39.2-40.5c19.8,0,34.6,12.4,34.6,30.8C633.9,157.3,633.4,161.9,632.6,164.6z
M599.9,136.4c-8.8,0-16.4,5-18.2,17.1H615C616.8,144.1,610.7,136.4,599.9,136.4z"/>
<path class="st1" d="M685.9,205.9c-25.2,0-43.7-18.2-43.7-41.8c0-23.4,18.5-41.8,43.7-41.8c25,0,43.6,18.4,43.6,41.8
C729.5,187.7,710.9,205.9,685.9,205.9z M685.9,137.6c-14,0-23.2,10.8-23.2,26.5c0,15.8,9.4,26.5,23.2,26.5s23-10.6,23-26.5
C709,148.4,699.8,137.6,685.9,137.6z"/>
<path class="st1" d="M782.6,163.7h-19.1V203h-22V95h41c25.9,0,37.4,15.8,37.4,34.4C820,148.1,808.5,163.7,782.6,163.7z M779,110.6
h-15.5v37.4H779c14.2,0,19.3-8.5,19.3-18.7C798.2,119.3,793.2,110.6,779,110.6z"/>
<path class="st1" d="M889.5,203l-0.7-12.4c-6.5,9.5-18,14.6-29,14.6c-21.1,0-36.5-17.6-36.5-41s15.5-41,36.5-41
c11,0,22.5,5,29,14.6l0.7-12.4h18.9V203H889.5z M866.3,138.5c-12.2,0-22.1,9.5-22.1,25.6s9.9,25.6,22.1,25.6
c12.2,0,22.1-9.5,22.1-25.6S878.5,138.5,866.3,138.5z"/>
<path class="st1" d="M981.1,203v-43c0-15.1-5.2-20.2-14.8-20.2c-9.9,0-20.7,9-20.7,19.8V203h-20.9v-77.8h19.1l0.9,14.4
c5.2-9.9,16.9-16.6,28.8-16.6c20.7,0,28.4,14.4,28.4,33.7V203H981.1z"/>
<path class="st1" d="M1079.9,203l-0.7-12.4c-6.5,9.5-18,14.6-29,14.6c-21.1,0-36.5-17.6-36.5-41s15.5-41,36.5-41
c10.4,0,21.1,4.3,27.7,12.8V95h20.9v108H1079.9z M1056.7,138.5c-12.2,0-22.1,9.5-22.1,25.6s9.9,25.6,22.1,25.6
c12.2,0,22.1-9.5,22.1-25.6S1069,138.5,1056.7,138.5z"/>
<path class="st1" d="M1176.9,203l-0.7-12.4c-6.5,9.5-18,14.6-29,14.6c-21.1,0-36.5-17.6-36.5-41s15.5-41,36.5-41
c11,0,22.5,5,29,14.6l0.7-12.4h18.9V203H1176.9z M1153.7,138.5c-12.2,0-22.1,9.5-22.1,25.6s9.9,25.6,22.1,25.6
c12.2,0,22.1-9.5,22.1-25.6S1166,138.5,1153.7,138.5z"/>
<path class="st1" d="M1238,205.5c-16,0-27.9-6.8-31.1-8.8l3.4-14.4c6.3,3.8,15.8,8.6,27.4,8.6c8.3,0,14-2.5,14-9
c0-5.6-5.9-7.6-16.6-10.1c-19.1-4.1-25.9-14.2-25.9-25.2c0-12.2,9.5-23.8,30.6-23.8c12.8,0,23.9,5.6,26.5,7l-3.4,13.7
c-6.7-4-14.8-6.5-22.5-6.5c-8.5,0-12.6,2.9-12.6,7.6c0,5.2,5.4,7.6,13.7,9.5c20.5,4.3,28.8,13.9,28.8,24.3
C1270.2,195.2,1257.9,205.5,1238,205.5z"/>
</g>
<rect x="243.2" y="73.2" class="st1" width="24.1" height="50"/>
<rect x="243.2" y="176" class="st1" width="24.1" height="50"/>
<rect x="281.1" y="114.4" class="st1" width="24.1" height="50"/>
<path class="st1" d="M239.1,8.2c-76.3,0-138.5,62.1-138.5,138.5c0,76.3,62.1,138.5,138.5,138.5S377.5,223,377.5,146.7
C377.5,70.3,315.4,8.2,239.1,8.2z M352.5,146.7c0,16.1-3.4,31.4-9.5,45.3v-90.6C349.1,115.2,352.5,130.6,352.5,146.7z M305.2,238.8
v-21.6h-24.1V252c-13,5.2-27.2,8.1-42,8.1c-3.5,0-7-0.2-10.5-0.5V114.3h-24.1v140.4c-45.7-14.7-78.9-57.6-78.9-108.1
c0-62.6,50.9-113.5,113.5-113.5c31.1,0,59.4,12.6,79.9,33v160.3h0.7C315.2,231,310.3,235.1,305.2,238.8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1,6 @@
{{ fullname }}
{{ underline }}
.. currentmodule:: {{ module.split('.')[0] }}
.. automethod:: {{ (module.split('.')[1:] + [objname]) | join('.') }}
+10
View File
@@ -0,0 +1,10 @@
{% set redirect = redirects[pagename.split("/")[-1]] %}
<html>
<head>
<meta http-equiv="Refresh" content="0; url={{ redirect }}.html" />
<title>This page has moved</title>
</head>
<body>
<p>This page has moved <a href="{{ redirect }}.html">here</a>.</p>
</body>
</html>
+53
View File
@@ -0,0 +1,53 @@
# About GeoPandas
```{toctree}
:maxdepth: 2
:caption: About
:hidden:
Team <about/team>
Citing <about/citing>
Logo <about/logo>
```
GeoPandas is an open source project to add support for geographic data to pandas objects. It
currently implements `GeoSeries` and `GeoDataFrame` types which are subclasses of
`pandas.Series` and `pandas.DataFrame` respectively. GeoPandas objects can act on
`shapely` geometry objects and perform geometric operations.
GeoPandas is a community-led project written, used and supported by a wide range of
people from all around of world of a large variety of backgrounds. Want to get involved
in the community? See our [community guidelines](community).
GeoPandas will always be 100% open source software, free for all to use and released
under the liberal terms of the BSD-3-Clause license.
```{container} button
{doc}`Team <about/team>`
{doc}`Citing <about/citing>` {doc}`Logo <about/logo>`
```
## Project history
Kelsey Jordahl founded GeoPandas project in 2013 during the Scipy Conference and
released a version 0.1.0 in July 2014. In 2016, Joris Van den Bossche took the lead and
became the maintainer of the project. Since the beginning, GeoPandas is a BSD-licensed
open-source project supported by a [community of
contributors](https://github.com/geopandas/geopandas/graphs/contributors) from around
the world and is now maintained by a [team](about/team) of core developers.
In 2020 GeoPandas became [NumFOCUS Affiliated
Project](https://numfocus.org/sponsored-projects/affiliated-projects) and received two
[Small Development Grants](https://numfocus.org/programs/sustainability) to support its
development.
## Timeline
- **2013**: Beginning of the development
- **2014**: GeoPandas 0.1.0 released
- **2020**: GeoPandas became [NumFOCUS Affiliated
Project](https://numfocus.org/sponsored-projects/affiliated-projects)
+50
View File
@@ -0,0 +1,50 @@
# Citing
When citing GeoPandas, you can use [Zenodo DOI](https://zenodo.org/record/3946761#.Xy24LC2ZPOQ) for each release.
Below is the example of resulting BiBTeX record for GeoPandas 0.8.1 and a reference using APA 6<sup>th</sup> ed.
_Kelsey Jordahl, Joris Van den Bossche, Martin Fleischmann, Jacob Wasserman, James McBride, Jeffrey Gerard, … François Leblanc. (2020, July 15). geopandas/geopandas: v0.8.1 (Version v0.8.1). Zenodo. http://doi.org/10.5281/zenodo.3946761_
```
@software{kelsey_jordahl_2020_3946761,
author = {Kelsey Jordahl and
Joris Van den Bossche and
Martin Fleischmann and
Jacob Wasserman and
James McBride and
Jeffrey Gerard and
Jeff Tratner and
Matthew Perry and
Adrian Garcia Badaracco and
Carson Farmer and
Geir Arne Hjelle and
Alan D. Snow and
Micah Cochran and
Sean Gillies and
Lucas Culbertson and
Matt Bartos and
Nick Eubank and
maxalbert and
Aleksey Bilogur and
Sergio Rey and
Christopher Ren and
Dani Arribas-Bel and
Leah Wasser and
Levi John Wolf and
Martin Journois and
Joshua Wilson and
Adam Greenhall and
Chris Holdgraf and
Filipe and
François Leblanc},
title = {geopandas/geopandas: v0.8.1},
month = jul,
year = 2020,
publisher = {Zenodo},
version = {v0.8.1},
doi = {10.5281/zenodo.3946761},
url = {https://doi.org/10.5281/zenodo.3946761}
}
```
+84
View File
@@ -0,0 +1,84 @@
# GeoPandas logo
GeoPandas project uses a logo derived from [`pandas` logo](https://pandas.pydata.org/about/citing.html), enclosing it in a globe illustrating the geographic nature of our data.
## Versions
We have four versions of our logo:
### Primary logo
The primary logo should be used in a majority of cases. Inverted logo or icon should be used only when necessary.
```{image} ../_static/logo/geopandas_logo.png
:alt: geopandas-logo
:align: center
```
### Inverted colors
If you want to place the GeoPandas logo on a dark background, use the inverted version.
```{image} ../_static/logo/geopandas_logo_green.png
:alt: geopandas-logo-green
:align: center
```
### Icon
Although it is possible to use icon independently, we would prefer using the complete variant above.
```{image} ../_static/logo/geopandas_icon.png
:alt: geopandas-icon
:width: 25%
:align: center
```
### Inverted icon
```{image} ../_static/logo/geopandas_icon_green.png
:alt: geopandas-icon-green
:width: 25%
:align: center
```
## Download
You can download all version in SVG and PNG from [GitHub repository](https://github.com/geopandas/geopandas/tree/main/doc/source/_static/logo).
## Colors
Pink and yellow accent colors are shared with `pandas`.
### Green
```{raw} html
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="75" style="float: left">
<circle cx="33" cy="33" r="33" fill="#139C5A"></circle>
</svg>
```
**HEX:** #139C5A
**RGB:** (19, 156, 90)
### Yellow
```{raw} html
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="75" style="float: left">
<circle cx="33" cy="33" r="33" fill="#FFCA00"></circle>
</svg>
```
**HEX:** #FFCA00
**RGB:** (255, 202, 0)
### Pink
```{raw} html
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="75" style="float: left">
<circle cx="33" cy="33" r="33" fill="#E70488"></circle>
</svg>
```
**HEX:** #E70488
**RGB:** ((31, 4, 136)
+5
View File
@@ -0,0 +1,5 @@
# Roadmap
## Roadmap for GeoPandas 1.0
WIP
+20
View File
@@ -0,0 +1,20 @@
# Team
## Contributors
GeoPandas is developed by more than [100 volunteer contributors](https://github.com/geopandas/geopandas/graphs/contributors).
## Core developers
- Joris Van den Bossche - **lead maintainer** | [@jorisvandenbossche](https://github.com/jorisvandenbossche)
- Martin Fleischmann | [@martinfleis](https://github.com/martinfleis)
- James McBride | [@jdmcbr](https://github.com/jdmcbr)
- Brendan Ward | [@brendan-ward](https://github.com/brendan-ward)
- Levi Wolf | [@ljwolf](https://github.com/ljwolf)
## Founder
- Kelsey Jordahl | [@kjordahl](https://github.com/kjordahl)
## Alumni developers
- Jacob Wasserman | [@jwass](https://github.com/jwass)
-1
View File
@@ -1 +0,0 @@
.. include:: ../../CHANGELOG.md
+31
View File
@@ -0,0 +1,31 @@
Community
---------
GeoPandas is a community-led project written, used and supported by a wide range of
people from all around of world of a large variety of backgrounds. Everyone is welcome,
each small contribution, no matter if it is a fix of a typo in the documentation, bug
report, an idea, or a question, is valuable. As a member of our community, you should
adhere to the principles presented in the :doc:`Code of Conduct
<community/code_of_conduct>`.
If you'd like to contribute, please read the :doc:`Contributing guide
<community/contributing>`. It will help you to understand the way GeoPandas development
works and us to review your contribution.
GeoPandas is a part of the broader Python :doc:`ecosystem <community/ecosystem>`. It
depends on a range of great tools, and various packages are built on top of GeoPandas
addressing specific needs in geospatial data processing, analysis and visualization.
.. container:: button
:doc:`Contributing <community/contributing>` :doc:`Code of Conduct <community/code_of_conduct>`
:doc:`Ecosystem <community/ecosystem>`
.. toctree::
:maxdepth: 2
:caption: Community
:hidden:
Contributing <community/contributing>
Code of Conduct <community/code_of_conduct>
Ecosystem <community/ecosystem>
@@ -92,7 +92,7 @@ free to contact the Code of Conduct Committee at
8. **A simple apology can go a long way**. It can often de-escalate a situation,
and telling someone that you are sorry is an act of empathy that doesnt
automatically imply an admission of guilt.
automatically imply an admission of guilt.
Reporting
---------
@@ -21,11 +21,9 @@ In particular, when submitting a pull request:
- All existing tests should pass. Please make sure that the test
suite passes, both locally and on
`Travis CI <https://travis-ci.org/geopandas/geopandas>`_. Status on
Travis will be visible on a pull request. If you want to enable
Travis CI on your own fork, please read the pandas guidelines link
above or the
`getting started docs <http://about.travis-ci.org/docs/user/getting-started/>`_.
`GitHub Actions <https://github.com/geopandas/geopandas/actions>`_. Status on
GHA will be visible on a pull request. GHA are automatically enabled
on your own fork as well. To trigger a check, make a PR to your own fork.
- New functionality should include tests. Please write reasonable
tests for your code and make sure that they pass on your pull request.
@@ -46,7 +44,7 @@ In particular, when submitting a pull request:
imports when possible, and explicit relative imports for local
imports when necessary in tests.
- GeoPandas supports Python 3.5+ only. The last version of GeoPandas
- GeoPandas supports Python 3.7+ only. The last version of GeoPandas
supporting Python 2 is 0.6.
@@ -84,7 +82,7 @@ Some great resources for learning Git:
* Software Carpentry's `Git Tutorial <http://swcarpentry.github.io/git-novice/>`_
* `Atlassian <https://www.atlassian.com/git/tutorials/what-is-version-control>`_
* the `GitHub help pages <http://help.github.com/>`_.
* Matthew Brett's `Pydagogue <http://matthew-brett.github.com/pydagogue/>`_.
* Matthew Brett's `Pydagogue <https://matthew-brett.github.io/pydagogue/>`_.
Getting started with Git
~~~~~~~~~~~~~~~~~~~~~~~~
@@ -109,16 +107,14 @@ want to clone your fork to your machine::
This creates the directory `geopandas-yourname` and connects your repository to
the upstream (main project) *GeoPandas* repository.
The testing suite will run automatically on Travis-CI once your pull request is
submitted. However, if you wish to run the test suite on a branch prior to
submitting the pull request, then Travis-CI needs to be hooked up to your
GitHub repository. Instructions for doing so are `here
<http://about.travis-ci.org/docs/user/getting-started/>`__.
The testing suite will run automatically on GitHub Actions once your pull request is
submitted. The test suite will also automatically run on your branch so you can
check it prior to submitting the pull request.
Creating a branch
~~~~~~~~~~~~~~~~~~
You want your master branch to reflect only production-ready code, so create a
You want your main branch to reflect only production-ready code, so create a
feature branch for making your changes. For example::
git branch shiny-new-feature
@@ -133,12 +129,12 @@ changes in this branch specific to one bug or feature so it is clear
what the branch brings to *GeoPandas*. You can have many shiny-new-features
and switch in between them using the git checkout command.
To update this branch, you need to retrieve the changes from the master branch::
To update this branch, you need to retrieve the changes from the main branch::
git fetch upstream
git rebase upstream/master
git rebase upstream/main
This will replay your commits on top of the latest GeoPandas git master. If this
This will replay your commits on top of the latest GeoPandas git main. If this
leads to merge conflicts, you must resolve these before submitting your pull
request. If you have uncommitted changes, you will need to ``stash`` them prior
to updating. This will effectively store your changes and they can be reapplied
@@ -159,7 +155,23 @@ An easy way to create a *GeoPandas* development environment is as follows:
- Make sure that you have :ref:`cloned the repository <contributing.forking>`
- ``cd`` to the *geopandas** source directory
Tell conda to create a new environment, named ``geopandas_dev``, or any other name you would like
Using the provided environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*GeoPandas* provides an environment which includes the required dependencies for development.
The environment file is located in the top level of the repo and is named ``environment-dev.yml``.
You can create this environment by navigating to the the *GeoPandas* source directory
and running::
conda env create -f environment-dev.yml
This will create a new conda environment named ``geopandas_dev``.
Creating the environment manually
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Alternatively, it is possible to create a development environment manually. To do this,
tell conda to create a new environment named ``geopandas_dev``, or any other name you would like
for this environment, by running::
conda create -n geopandas_dev python
@@ -167,6 +179,9 @@ for this environment, by running::
This will create the new environment, and not touch any of your existing environments,
nor any existing python installation.
Working with the environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To work in this environment, you need to ``activate`` it. The instructions below
should work for both Windows, Mac and Linux::
@@ -187,12 +202,14 @@ See the full conda docs `here <http://conda.pydata.org/docs>`__.
At this point you can easily do a *development* install, as detailed in the next sections.
3) Installing Dependencies
--------------------------
To run *GeoPandas* in an development environment, you must first install
*GeoPandas*'s dependencies. We suggest doing so using the following commands
(executed after your development environment has been activated)::
*GeoPandas*'s dependencies. If you used the provided environment in section 2, skip this
step and continue to section 4. If you created the environment manually, we suggest installing
dependencies using the following commands (executed after your development environment has been activated)::
conda install -c conda-forge pandas fiona shapely pyproj rtree pytest
@@ -251,27 +268,42 @@ install *GeoPandas*) by typing::
6) Updating the Documentation
-----------------------------
*GeoPandas* documentation resides in the `doc` folder. Changes to the docs are
make by modifying the appropriate file in the `source` folder within `doc`.
*GeoPandas* docs use reStructuredText syntax, `which is explained here <http://www.sphinx-doc.org/en/stable/rest.html#rst-primer>`_
and the docstrings follow the `Numpy Docstring standard <https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt>`_.
*GeoPandas* documentation resides in the ``doc`` folder. Changes to the docs are made by
modifying the appropriate file in the ``source`` folder within ``doc``. *GeoPandas* docs use
mixture of reStructuredText syntax for ``rst`` files, `which is explained here
<http://www.sphinx-doc.org/en/stable/rest.html#rst-primer>`_ and MyST syntax for ``md``
files `explained here <https://myst-parser.readthedocs.io/en/latest/index.html>`_.
The docstrings follow the `Numpy Docstring standard
<https://github.com/numpy/numpy/blob/main/doc/HOWTO_DOCUMENT.rst.txt>`_. Some pages
and examples are Jupyter notebooks converted to docs using `nbsphinx
<https://nbsphinx.readthedocs.io/>`_. Jupyter notebooks should be stored without the output.
We highly encourage you to follow the `Google developer documentation style guide
<https://developers.google.com/style/highlights>`_ when updating or creating new documentation.
Once you have made your changes, you may try if they render correctly by
building the docs using sphinx. To do so, you can navigate to the `doc` folder
building the docs using sphinx. To do so, you can navigate to the `doc` folder::
cd doc
and type::
make html
The resulting html pages will be located in `doc/build/html`. In case of any
errors, you can try to use `make html` within a new environment based on
environment.yml specification in the `doc` folder. Using conda::
The resulting html pages will be located in ``doc/build/html``.
In case of any errors, you can try to use ``make html`` within a new environment based on
environment.yml specification in the ``doc`` folder. You may need to register Jupyter kernel as
``geopandas_docs``. Using conda::
cd doc
conda env create -f environment.yml
conda activate geopandas_docs
python -m ipykernel install --user --name geopandas_docs
make html
For minor updates, you can skip whole `make html` part as reStructuredText syntax
is usually quite straightforward.
For minor updates, you can skip the ``make html`` part as reStructuredText and MyST
syntax are usually quite straightforward.
7) Submitting a Pull Request
@@ -292,19 +324,19 @@ and uses `Black <https://black.readthedocs.io/en/stable/>`_ and
`Flake8 <http://flake8.pycqa.org/en/latest/>`_ to ensure a consistent code
format throughout the project.
Continuous Integration (Travis CI) will run those tools and
Continuous Integration (GitHub Actions) will run those tools and
report any stylistic errors in your code. Therefore, it is helpful before
submitting code to run the check yourself::
black geopandas
git diff upstream/master -u -- "*.py" | flake8 --diff
git diff upstream/main -u -- "*.py" | flake8 --diff
to auto-format your code. Additionally, many editors have plugins that will
apply ``black`` as you edit files.
Optionally (but recommended), you can setup `pre-commit hooks <https://pre-commit.com/>`_
to automatically run ``black`` and ``flake8`` when you make a git commit. This
can be done by installing ``pre-commit``::
to automatically run ``black`` and ``flake8`` when you make a git commit. If you did not
use the provided development environment in ``environment-dev.yml``, you must first install ``pre-commit``::
$ python -m pip install pre-commit
@@ -316,3 +348,31 @@ From the root of the geopandas repository, you should then install the
Then ``black`` and ``flake8`` will be run automatically
each time you commit changes. You can skip these checks with
``git commit --no-verify``.
Commit message conventions
--------------------------
Commit your changes to your local repository with an explanatory message. GeoPandas
uses the pandas convention for commit message prefixes and layout. Here are
some common prefixes along with general guidelines for when to use them:
* ENH: Enhancement, new functionality
* BUG: Bug fix
* DOC: Additions/updates to documentation
* TST: Additions/updates to tests
* BLD: Updates to the build process/scripts
* PERF: Performance improvement
* TYP: Type annotations
* CLN: Code cleanup
The following defines how a commit message should be structured. Please refer to the
relevant GitHub issues in your commit message using GH1234 or #1234. Either style
is fine, but the former is generally preferred:
* a subject line with `< 80` chars.
* One blank line.
* Optionally, a commit message body.
Now you can commit your changes in your local repository::
git commit -m
+284
View File
@@ -0,0 +1,284 @@
# Ecosystem
## GeoPandas dependencies
GeoPandas brings together the full capability of `pandas` and the open-source geospatial
tools `Shapely`, which brings manipulation and analysis of geometric objects backed by
[`GEOS`](https://trac.osgeo.org/geos) library, `Fiona`, allowing us to read and write
geographic data files using [`GDAL`](https://gdal.org), and `pyproj`, a library for
cartographic projections and coordinate transformations, which is a Python interface to
[`PROJ`](https://proj.org).
Furthermore, GeoPandas has several optional dependencies as `rtree`, `pygeos`,
`mapclassify`, or `geopy`.
### Required dependencies
#### [pandas](https://github.com/pandas-dev/pandas)
`pandas` is a Python package that provides fast, flexible, and expressive data
structures designed to make working with structured (tabular, multidimensional,
potentially heterogeneous) and time series data both easy and intuitive. It aims to be
the fundamental high-level building block for doing practical, real world data analysis
in Python. Additionally, it has the broader goal of becoming the most powerful and
flexible open source data analysis / manipulation tool available in any language. It is
already well on its way toward this goal.
#### [Shapely](https://github.com/Toblerity/Shapely)
`Shapely` is a BSD-licensed Python package for manipulation and analysis of planar
geometric objects. It is based on the widely deployed `GEOS` (the engine of PostGIS) and
`JTS` (from which `GEOS` is ported) libraries. `Shapely` is not concerned with data
formats or coordinate systems, but can be readily integrated with packages that are.
#### [Fiona](https://github.com/Toblerity/Fiona)
`Fiona` is `GDALs` neat and nimble vector API for Python programmers. Fiona is designed
to be simple and dependable. It focuses on reading and writing data in standard Python
IO style and relies upon familiar Python types and protocols such as files,
dictionaries, mappings, and iterators instead of classes specific to `OGR`. Fiona can
read and write real-world data using multi-layered GIS formats and zipped virtual file
systems and integrates readily with other Python GIS packages such as `pyproj`, `Rtree`,
and `Shapely`.
#### [pyproj](https://github.com/pyproj4/pyproj)
`pyproj` is a Python interface to `PROJ` (cartographic projections and coordinate
transformations library). GeoPandas uses a `pyproj.crs.CRS` object to keep track of the
projection of each `GeoSeries` and its `Transformer` object to manage re-projections.
### Optional dependencies
#### [rtree](https://github.com/Toblerity/rtree)
`Rtree` is a ctypes Python wrapper of `libspatialindex` that provides a number of
advanced spatial indexing features for the spatially curious Python user.
#### [PyGEOS](https://github.com/pygeos/pygeos)
`PyGEOS` is a C/Python library with vectorized geometry functions. The geometry
operations are done in the open-source geometry library `GEOS`. PyGEOS wraps these
operations in `NumPy` ufuncs providing a performance improvement when operating on
arrays of geometries.
#### [mapclassify](https://github.com/pysal/mapclassify)
`mapclassify` provides functionality for Choropleth map classification. Currently,
fifteen different classification schemes are available, including a highly-optimized
implementation of Fisher-Jenks optimal classification. Each scheme inherits a common
structure that ensures computations are scalable and supports applications in streaming
contexts.
#### [geopy](https://github.com/geopy/geopy)
`geopy` is a Python client for several popular geocoding web services. `geopy` makes it
easy for Python developers to locate the coordinates of addresses, cities, countries,
and landmarks across the globe using third-party geocoders and other data sources.
#### [matplotlib](https://github.com/matplotlib/matplotlib)
`Matplotlib` is a comprehensive library for creating static, animated, and interactive
visualizations in Python. Matplotlib produces publication-quality figures in a variety
of hardcopy formats and interactive environments across platforms. Matplotlib can be
used in Python scripts, the Python and IPython shell, web application servers, and
various graphical user interface toolkits.
## GeoPandas ecosystem
Various packages are built on top of GeoPandas addressing specific geospatial data
processing needs, analysis, and visualization. Below is an incomplete list (in no
particular order) of tools which form the GeoPandas-related Python ecosystem.
### Spatial analysis and Machine Learning
#### [PySAL](https://github.com/pysal/pysal)
`PySAL`, the Python spatial analysis library, is an open source cross-platform library
for geospatial data science with an emphasis on geospatial vector data written in
Python. `PySAL` is a family of packages, some of which are listed below.
##### [libpysal](https://github.com/pysal/libpysal)
`libpysal` provides foundational algorithms and data structures that support the rest of
the library. This currently includes the following modules: input/output (`io`), which
provides readers and writers for common geospatial file formats; weights (`weights`),
which provides the main class to store spatial weights matrices, as well as several
utilities to manipulate and operate on them; computational geometry (`cg`), with several
algorithms, such as Voronoi tessellations or alpha shapes that efficiently process
geometric shapes; and an additional module with example data sets (`examples`).
##### [esda](https://github.com/pysal/esda)
`esda` implements methods for the analysis of both global (map-wide) and local (focal)
spatial autocorrelation, for both continuous and binary data. In addition, the package
increasingly offers cutting-edge statistics about boundary strength and measures of
aggregation error in statistical analyses.
##### [segregation](https://github.com/pysal/segregation)
`segregation` package calculates over 40 different segregation indices and provides a
suite of additional features for measurement, visualization, and hypothesis testing that
together represent the state of the art in quantitative segregation analysis.
##### [mgwr](https://github.com/pysal/mgwr)
`mgwr` provides scalable algorithms for estimation, inference, and prediction using
single- and multi-scale geographically weighted regression models in a variety of
generalized linear model frameworks, as well as model diagnostics tools.
##### [tobler](https://github.com/pysal/tobler)
`tobler` provides functionality for areal interpolation and dasymetric mapping.
`tobler` includes functionality for interpolating data using area-weighted approaches,
regression model-based approaches that leverage remotely-sensed raster data as auxiliary
information, and hybrid approaches.
#### [movingpandas](https://github.com/anitagraser/movingpandas)
`MovingPandas` is a package for dealing with movement data. `MovingPandas` implements a
`Trajectory` class and corresponding methods based on GeoPandas. A trajectory has a
time-ordered series of point geometries. These points and associated attributes are
stored in a `GeoDataFrame`. `MovingPandas` implements spatial and temporal data access
and analysis functions as well as plotting functions.
#### [momepy](https://github.com/martinfleis/momepy)
`momepy` is a library for quantitative analysis of urban form - urban morphometrics. It
is built on top of `GeoPandas`, `PySAL` and `networkX`. `momepy` aims to provide a wide
range of tools for a systematic and exhaustive analysis of urban form. It can work with
a wide range of elements, while focused on building footprints and street networks.
#### [geosnap](https://github.com/spatialucr/geosnap)
`geosnap` makes it easier to explore, model, analyze, and visualize the social and
spatial dynamics of neighborhoods. `geosnap` provides a suite of tools for creating
socio-spatial datasets, harmonizing those datasets into consistent set of time-static
boundaries, modeling bespoke neighborhoods and prototypical neighborhood types, and
modeling neighborhood change using classic and spatial statistical methods. It also
provides a set of static and interactive visualization tools to help you display and
understand the critical information at each step of the process.
#### [mesa-geo](https://github.com/Corvince/mesa-geo)
`mesa-geo` implements a GeoSpace that can host GIS-based GeoAgents, which are like
normal Agents, except they have a shape attribute that is a `Shapely` object. You can
use `Shapely` directly to create arbitrary shapes, but in most cases you will want to
import your shapes from a file. Mesa-geo allows you to create GeoAgents from any vector
data file (e.g. shapefiles), valid GeoJSON objects or a GeoPandas `GeoDataFrame`.
#### [Pyspatialml](https://github.com/stevenpawley/Pyspatialml)
`Pyspatialml` is a Python module for applying `scikit-learn` machine learning models to
'stacks' of raster datasets. Pyspatialml includes functions and classes for working with
multiple raster datasets and performing a typical machine learning workflow consisting
of extracting training data and applying the predict or `predict_proba` methods of
`scikit-learn` estimators to a stack of raster datasets. Pyspatialml is built upon the
`rasterio` Python module for all of the heavy lifting, and is also designed for working
with vector data using the `geopandas` module.
#### [PyGMI](https://github.com/Patrick-Cole/pygmi)
`PyGMI` stands for Python Geoscience Modelling and Interpretation. It is a modelling and
interpretation suite aimed at magnetic, gravity and other datasets.
### Visualization
#### [hvPlot](https://hvplot.holoviz.org/user_guide/Geographic_Data.html#Geopandas)
`hvPlot` provides interactive Bokeh-based plotting for GeoPandas
dataframes and series using the same API as the Matplotlib `.plot()`
support that comes with GeoPandas. hvPlot makes it simple to pan and zoom into
your plots, use widgets to explore multidimensional data, and render even the
largest datasets in web browsers using [Datashader](https://datashader.org).
#### [contextily](https://github.com/geopandas/contextily)
`contextily` is a small Python 3 (3.6 and above) package to retrieve tile maps from the
internet. It can add those tiles as basemap to `matplotlib` figures or write tile maps
to disk into geospatial raster files. Bounding boxes can be passed in both WGS84
(EPSG:4326) and Spheric Mercator (EPSG:3857).
#### [cartopy](https://github.com/SciTools/cartopy)
`Cartopy` is a Python package designed to make drawing maps for data analysis and
visualisation easy. It features: object oriented projection definitions; point, line,
polygon and image transformations between projections; integration to expose advanced
mapping in `Matplotlib` with a simple and intuitive interface; powerful vector data
handling by integrating shapefile reading with `Shapely` capabilities.
#### [bokeh](https://github.com/bokeh/bokeh)
`Bokeh` is an interactive visualization library for modern web browsers. It provides
elegant, concise construction of versatile graphics, and affords high-performance
interactivity over large or streaming datasets. `Bokeh` can help anyone who would like
to quickly and easily make interactive plots, dashboards, and data applications.
#### [folium](https://github.com/python-visualization/folium)
`folium` builds on the data wrangling strengths of the Python ecosystem and the mapping
strengths of the `Leaflet.js` library. Manipulate your data in Python, then visualize it
in a `Leaflet` map via `folium`.
#### [kepler.gl](https://github.com/keplergl/kepler.gl)
`Kepler.gl` is a data-agnostic, high-performance web-based application for visual
exploration of large-scale geolocation data sets. Built on top of Mapbox GL and
`deck.gl`, `kepler.gl` can render millions of points representing thousands of trips and
perform spatial aggregations on the fly.
#### [geoplot](https://github.com/ResidentMario/geoplot)
`geoplot` is a high-level Python geospatial plotting library. It's an extension to
`cartopy` and `matplotlib` which makes mapping easy: like `seaborn` for geospatial. It
comes with the high-level plotting API, native projection support and compatibility with
`matplotlib`.
#### [GeoViews](https://github.com/holoviz/geoviews)
`GeoViews` is a Python library that makes it easy to explore and
visualize any data that includes geographic locations, with native
support for GeoPandas dataframes and series objects. It has
particularly powerful support for multidimensional meteorological and
oceanographic datasets, such as those used in weather, climate, and
remote sensing research, but is useful for almost anything that you
would want to plot on a map!
#### [EarthPy](https://github.com/earthlab/earthpy)
`EarthPy` is a python package that makes it easier to plot and work with spatial raster
and vector data using open source tools. `Earthpy` depends upon `geopandas` which has a
focus on vector data and `rasterio` with facilitates input and output of raster data
files. It also requires `matplotlib` for plotting operations. `EarthPys` goal is to
make working with spatial data easier for scientists.
#### [splot](https://github.com/pysal/splot)
`splot` provides statistical visualizations for spatial analysis. It methods for
visualizing global and local spatial autocorrelation (through Moran scatterplots and
cluster maps), temporal analysis of cluster dynamics (through heatmaps and rose
diagrams), and multivariate choropleth mapping (through value-by-alpha maps). A high
level API supports the creation of publication-ready visualizations
#### [legendgram](https://github.com/pysal/legendgram)
`legendgram` is a small package that provides "legendgrams" legends that visualize the
distribution of observations by color in a given map. These distributional
visualizations for map classification schemes assist in analytical cartography and
spatial data visualization.
### Geometry manipulation
#### [TopoJSON](https://github.com/mattijn/topojson)
`topojson` is a library for creating a TopoJSON encoding of nearly any
geographical object in Python. With topojson it is possible to reduce the size of
your geographical data, typically by orders of magnitude. It is able to do so through
eliminating redundancy through computation of a topology, fixed-precision integer
encoding of coordinates, and simplification and quantization of arcs.
#### [geocube](https://github.com/corteva/geocube)
Tool to convert geopandas vector data into rasterized `xarray` data.
### Data retrieval
#### [OSMnx](https://github.com/gboeing/osmnx)
`OSMnx` is a Python package that lets you download spatial data from OpenStreetMap and
model, project, visualize, and analyze real-world street networks. You can download and
model walkable, drivable, or bikeable urban networks with a single line of Python code
and then easily analyze and visualize them. You can just as easily download and work with
other infrastructure types, amenities/points of interest, building footprints, elevation
data, street bearings/orientations, and speed/travel time.
#### [pyrosm](https://github.com/HTenkanen/pyrosm)
`Pyrosm` is a Python library for reading OpenStreetMap data from Protocolbuffer Binary
Format -files (`*.osm.pbf`) into Geopandas `GeoDataFrames`. Pyrosm makes it easy to
extract various datasets from OpenStreetMap pbf-dumps including e.g. road networks,
buildings, Points of Interest (POI), landuse and natural elements. Also fully customized
queries are supported which makes it possible to parse the data from OSM with more
specific filters.
#### [geobr](https://github.com/ipeaGIT/geobr)
`geobr` is a computational package to download official spatial data sets of Brazil. The
package includes a wide range of geospatial data in geopackage format (like shapefiles
but better), available at various geographic scales and for various years with
harmonized attributes, projection and topology.
#### [cenpy](https://github.com/cenpy-devs/cenpy)
An interface to explore and query the US Census API and return Pandas `Dataframes`. This
package is intended for exploratory data analysis and draws inspiration from
sqlalchemy-like interfaces and `acs.R`. With separate APIs for application developers
and folks who only want to get their data quickly & painlessly, `cenpy` should meet the
needs of most who aim to get US Census Data into Python.
```{admonition} Expand this page
Do know a package which should be here? [Let us
know](https://github.com/geopandas/geopandas/issues) or [add it by
yourself](contributing.rst)!
```
+223 -93
View File
@@ -17,60 +17,56 @@ import warnings
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['IPython.sphinxext.ipython_console_highlighting',
'IPython.sphinxext.ipython_directive',
'sphinx_gallery.gen_gallery',
'sphinx.ext.autosummary',
'sphinx.ext.intersphinx',
'sphinx.ext.autodoc',
'recommonmark',
'numpydoc',
extensions = [
"IPython.sphinxext.ipython_console_highlighting",
"IPython.sphinxext.ipython_directive",
"sphinx_gallery.load_style",
"sphinx.ext.autosummary",
"sphinx.ext.intersphinx",
"sphinx.ext.autodoc",
"myst_parser",
"nbsphinx",
"numpydoc",
"sphinx_toggleprompt",
"matplotlib.sphinxext.plot_directive",
]
# continue doc build and only print warnings/errors in examples
ipython_warning_is_error = False
ipython_exec_lines = [
# ensure that dataframes are not truncated in the IPython code blocks
'import pandas as _pd',
"import pandas as _pd",
'_pd.set_option("display.max_columns", 20)',
'_pd.set_option("display.width", 100)'
'_pd.set_option("display.width", 100)',
]
# Fix issue with warnings from numpydoc (see discussion in PR #534)
numpydoc_show_class_members = False
def setup(app):
app.add_stylesheet('custom.css') # may also be an URL
app.add_css_file("custom.css") # may also be an URL
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
autosummary_generate = True
# Sphinx gallery configuration
sphinx_gallery_conf = {
'examples_dirs': ['../../examples'],
'filename_pattern': '^((?!sgskip).)*$',
'gallery_dirs': ['gallery'],
'doc_module': ('geopandas',),
'reference_url': {'matplotlib': 'http://matplotlib.org',
'numpy': 'http://docs.scipy.org/doc/numpy',
'scipy': 'http://docs.scipy.org/doc/scipy/reference',
'geopandas': None},
'backreferences_dir': 'reference'
}
# connect docs in other projects
intersphinx_mapping = {'pyproj': ('http://pyproj4.github.io/pyproj/stable/', None)}
nbsphinx_execute = "always"
nbsphinx_allow_errors = True
nbsphinx_kernel_name = "python3"
# suppress matplotlib warning in examples
warnings.filterwarnings(
"ignore",
@@ -80,193 +76,222 @@ warnings.filterwarnings(
)
# The suffix of source filenames.
source_suffix = ['.rst', '.md']
source_suffix = [".rst", ".md"]
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = u'GeoPandas'
copyright = u'20132019, GeoPandas developers'
project = u"GeoPandas"
copyright = u"20132022, GeoPandas developers"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
import geopandas
version = release = geopandas.__version__
release = release = geopandas.__version__
version = release
if "+" in version:
version, remainder = release.split("+")
if not remainder.startswith("0"):
version = version + ".dev+" + remainder.split(".")[0]
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_theme = "pydata_sphinx_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
html_theme_options = {
"search_bar_position": "sidebar",
"github_url": "https://github.com/geopandas/geopandas",
"twitter_url": "https://twitter.com/geopandas",
}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
html_logo = "_static/logo/geopandas_logo_web.svg"
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
html_favicon = "_static/logo/favicon.png"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# html_additional_pages = {}
# Add redirect for previously existing pages, each item is like `(from_old, to_new)`
moved_pages = [
# user guide
("aggregation_with_dissolve", "docs/user_guide/aggregation_with_dissolve"),
("data_structures", "docs/user_guide/data_structures"),
("geocoding", "docs/user_guide/geocoding"),
("geometric_manipulations", "docs/user_guide/geometric_manipulations"),
("indexing", "docs/user_guide/indexing"),
("io", "docs/user_guide/io"),
("mapping", "docs/user_guide/mapping"),
("mergingdata", "docs/user_guide/mergingdata"),
("missing_empty", "docs/user_guide/missing_empty"),
("projections", "docs/user_guide/projections"),
("set_operations", "docs/user_guide/set_operations"),
# other
("install", "getting_started/install"),
("reference", "docs/reference"),
("changelog", "docs/changelog"),
("code_of_conduct", "community/code_of_conduct"),
("contributing", "community/contributing"),
]
html_additional_pages = {page[0]: "redirect.html" for page in moved_pages}
html_context = {"redirects": {old: new for old, new in moved_pages}}
# If false, no module index is generated.
#html_domain_indices = True
# html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'GeoPandasdoc'
htmlhelp_basename = "GeoPandasdoc"
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'GeoPandas.tex', u'GeoPandas Documentation',
u'Kelsey Jordahl', 'manual'),
("index", "GeoPandas.tex", u"GeoPandas Documentation", u"Kelsey Jordahl", "manual")
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'geopandas', u'GeoPandas Documentation',
[u'Kelsey Jordahl'], 1)
]
man_pages = [("index", "geopandas", u"GeoPandas Documentation", [u"Kelsey Jordahl"], 1)]
# If true, show URL addresses after external links.
#man_show_urls = False
# man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
@@ -275,16 +300,121 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'GeoPandas', u'GeoPandas Documentation',
u'Kelsey Jordahl', 'GeoPandas', 'One line description of project.',
'Miscellaneous'),
(
"index",
"GeoPandas",
u"GeoPandas Documentation",
u"Kelsey Jordahl",
"GeoPandas",
"One line description of project.",
"Miscellaneous",
)
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# texinfo_show_urls = 'footnote'
nbsphinx_prolog = r"""
{% set docname = env.doc2path(env.docname, base=None) %}
.. only:: html
.. role:: raw-html(raw)
:format: html
.. note::
| This page was generated from `{{ docname }}`__.
| Interactive online version: :raw-html:`<a href="https://mybinder.org/v2/gh/geopandas/geopandas/main?urlpath=lab/tree/doc/source/{{ docname }}"><img alt="Binder badge" src="https://mybinder.org/badge_logo.svg" style="vertical-align:text-bottom"></a>`
__ https://github.com/geopandas/geopandas/blob/main/doc/source/{{ docname }}
"""
# --Options for sphinx extensions -----------------------------------------------
# connect docs in other projects
intersphinx_mapping = {
"cartopy": (
"https://scitools.org.uk/cartopy/docs/latest/",
"https://scitools.org.uk/cartopy/docs/latest/objects.inv",
),
"contextily": (
"https://contextily.readthedocs.io/en/stable/",
"https://contextily.readthedocs.io/en/stable/objects.inv",
),
"fiona": (
"https://fiona.readthedocs.io/en/stable/",
"https://fiona.readthedocs.io/en/stable/objects.inv",
),
"folium": (
"https://python-visualization.github.io/folium/",
"https://python-visualization.github.io/folium/objects.inv",
),
"geoplot": (
"https://residentmario.github.io/geoplot/index.html",
"https://residentmario.github.io/geoplot/objects.inv",
),
"geopy": (
"https://geopy.readthedocs.io/en/stable/",
"https://geopy.readthedocs.io/en/stable/objects.inv",
),
"libpysal": (
"https://pysal.org/libpysal/",
"https://pysal.org/libpysal/objects.inv",
),
"mapclassify": (
"https://pysal.org/mapclassify/",
"https://pysal.org/mapclassify/objects.inv",
),
"matplotlib": (
"https://matplotlib.org/stable/",
"https://matplotlib.org/stable/objects.inv",
),
"pandas": (
"https://pandas.pydata.org/pandas-docs/stable/",
"https://pandas.pydata.org/pandas-docs/stable/objects.inv",
),
"pyarrow": ("https://arrow.apache.org/docs/", None),
"pyepsg": (
"https://pyepsg.readthedocs.io/en/stable/",
"https://pyepsg.readthedocs.io/en/stable/objects.inv",
),
"pygeos": (
"https://pygeos.readthedocs.io/en/latest/",
"https://pygeos.readthedocs.io/en/latest/objects.inv",
),
"pyproj": (
"https://pyproj4.github.io/pyproj/stable/",
"https://pyproj4.github.io/pyproj/stable/objects.inv",
),
"python": (
"https://docs.python.org/3",
"https://docs.python.org/3/objects.inv",
),
"rtree": (
"https://rtree.readthedocs.io/en/stable/",
"https://rtree.readthedocs.io/en/stable/objects.inv",
),
"rasterio": (
"https://rasterio.readthedocs.io/en/stable/",
"https://rasterio.readthedocs.io/en/stable/objects.inv",
),
"shapely": (
"https://shapely.readthedocs.io/en/stable/",
"https://shapely.readthedocs.io/en/stable/objects.inv",
),
"branca": (
"https://python-visualization.github.io/branca/",
"https://python-visualization.github.io/branca/objects.inv",
),
"xyzservices": (
"https://xyzservices.readthedocs.io/en/stable/",
"https://xyzservices.readthedocs.io/en/stable/objects.inv",
),
}
+19
View File
@@ -0,0 +1,19 @@
Documentation
-------------
The documentation of GeoPandas consists of four parts - :doc:`User Guide <docs/user_guide>` with explanation of the basic functionality, :doc:`Advanced Guide <docs/advanced_guide>` covering topics which assume knowledge of basics, :doc:`Examples <gallery/index>`, and :doc:`API reference <docs/reference>` detailing every class, method, function and attribute used implemented by GeoPandas.
.. container:: button
:doc:`User Guide <docs/user_guide>` :doc:`Advanced Guide <docs/advanced_guide>`
:doc:`Examples <gallery/index>` :doc:`API reference <docs/reference>`
.. toctree::
:maxdepth: 2
:caption: Documentation
User Guide <docs/user_guide>
Advanced Guide <docs/advanced_guide>
API reference <docs/reference>
Changelog <docs/changelog>
+20
View File
@@ -0,0 +1,20 @@
Advanced Guide
==============
The Advanced Guide covers advanced usage of GeoPandas. Each page focuses on a single
topic and outlines how it is implemented in GeoPandas, with reproducible examples.
If you don't know anything about GeoPandas, start with the :doc:`Introduction to
GeoPandas <../getting_started/introduction>`.
Basic topics can be found in the :doc:`User Guide <user_guide>` and further
specification in the :doc:`API Reference <reference>`.
.. note::
This section is currently work in progress. See the available pages below.
.. toctree::
:maxdepth: 2
user_guide/missing_empty
user_guide/reproject_fiona
+1
View File
@@ -0,0 +1 @@
.. include:: ../../../CHANGELOG.md
+20
View File
@@ -0,0 +1,20 @@
.. _reference:
API Reference
=============
The API Reference provides an overview of all public objects, functions and methods implemented in GeoPandas. All classes and function exposed in ``geopandas.*`` namespace plus those listed in the reference are public.
.. warning::
The ``geopandas.array`` and ``geopandas.base`` modules are private. Stable functionality in such modules is not guaranteed.
.. toctree::
:maxdepth: 2
GeoSeries <reference/geoseries>
GeoDataFrame <reference/geodataframe>
Input/output <reference/io>
Tools <reference/tools>
Spatial index <reference/sindex>
Testing <reference/testing>
+123
View File
@@ -0,0 +1,123 @@
============
GeoDataFrame
============
.. currentmodule:: geopandas
A ``GeoDataFrame`` is a tabular data structure that contains a column
which contains a ``GeoSeries`` storing geometry.
Constructor
-----------
.. autosummary::
:toctree: api/
GeoDataFrame
Serialization / IO / conversion
-------------------------------
.. autosummary::
:toctree: api/
GeoDataFrame.from_file
GeoDataFrame.from_features
GeoDataFrame.from_postgis
GeoDataFrame.to_file
GeoDataFrame.to_json
GeoDataFrame.to_parquet
GeoDataFrame.to_feather
GeoDataFrame.to_postgis
GeoDataFrame.to_wkb
GeoDataFrame.to_wkt
Projection handling
-------------------
.. autosummary::
:toctree: api/
GeoDataFrame.crs
GeoDataFrame.set_crs
GeoDataFrame.to_crs
GeoDataFrame.estimate_utm_crs
Active geometry handling
------------------------
.. autosummary::
:toctree: api/
GeoDataFrame.rename_geometry
GeoDataFrame.set_geometry
Aggregating and exploding
-------------------------
.. autosummary::
:toctree: api/
GeoDataFrame.dissolve
GeoDataFrame.explode
Spatial joins
-------------
.. autosummary::
:toctree: api/
GeoDataFrame.sjoin
GeoDataFrame.sjoin_nearest
Overlay operations
------------------
.. autosummary::
:toctree: api/
GeoDataFrame.clip
GeoDataFrame.overlay
Plotting
--------
.. autosummary::
:toctree: api/
GeoDataFrame.explore
.. autosummary::
:toctree: api/
:template: accessor_callable.rst
GeoDataFrame.plot
Spatial index
-------------
.. autosummary::
:toctree: api/
GeoDataFrame.sindex
GeoDataFrame.has_sindex
Indexing
--------
.. autosummary::
:toctree: api/
GeoDataFrame.cx
Interface
---------
.. autosummary::
:toctree: api/
GeoDataFrame.__geo_interface__
GeoDataFrame.iterfeatures
All pandas ``DataFrame`` methods are also available, although they may
not operate in a meaningful way on the ``geometry`` column. All methods
listed in `GeoSeries <geoseries>`__ work directly on an active geometry column of GeoDataFrame.
+196
View File
@@ -0,0 +1,196 @@
=========
GeoSeries
=========
.. currentmodule:: geopandas
Constructor
-----------
.. autosummary::
:toctree: api/
GeoSeries
General methods and attributes
------------------------------
.. autosummary::
:toctree: api/
GeoSeries.area
GeoSeries.boundary
GeoSeries.bounds
GeoSeries.total_bounds
GeoSeries.length
GeoSeries.geom_type
GeoSeries.distance
GeoSeries.representative_point
GeoSeries.exterior
GeoSeries.interiors
GeoSeries.x
GeoSeries.y
GeoSeries.z
Unary predicates
----------------
.. autosummary::
:toctree: api/
GeoSeries.is_empty
GeoSeries.is_ring
GeoSeries.is_simple
GeoSeries.is_valid
GeoSeries.has_z
Binary Predicates
-----------------
.. autosummary::
:toctree: api/
GeoSeries.contains
GeoSeries.crosses
GeoSeries.disjoint
GeoSeries.geom_equals
GeoSeries.geom_almost_equals
GeoSeries.geom_equals_exact
GeoSeries.intersects
GeoSeries.overlaps
GeoSeries.touches
GeoSeries.within
GeoSeries.covers
GeoSeries.covered_by
Set-theoretic Methods
---------------------
.. autosummary::
:toctree: api/
GeoSeries.difference
GeoSeries.intersection
GeoSeries.symmetric_difference
GeoSeries.union
Constructive Methods and Attributes
-----------------------------------
.. autosummary::
:toctree: api/
GeoSeries.buffer
GeoSeries.boundary
GeoSeries.centroid
GeoSeries.convex_hull
GeoSeries.envelope
GeoSeries.simplify
Affine transformations
----------------------
.. autosummary::
:toctree: api/
GeoSeries.affine_transform
GeoSeries.rotate
GeoSeries.scale
GeoSeries.skew
GeoSeries.translate
Aggregating and exploding
-------------------------
.. autosummary::
:toctree: api/
GeoSeries.unary_union
GeoSeries.explode
Serialization / IO / conversion
-------------------------------
.. autosummary::
:toctree: api/
GeoSeries.from_file
GeoSeries.from_wkb
GeoSeries.from_wkt
GeoSeries.from_xy
GeoSeries.to_file
GeoSeries.to_json
GeoSeries.to_wkb
GeoSeries.to_wkt
Projection handling
-------------------
.. autosummary::
:toctree: api/
GeoSeries.crs
GeoSeries.set_crs
GeoSeries.to_crs
GeoSeries.estimate_utm_crs
Missing values
--------------
.. autosummary::
:toctree: api/
GeoSeries.fillna
GeoSeries.isna
GeoSeries.notna
Overlay operations
------------------
.. autosummary::
:toctree: api/
GeoSeries.clip
Plotting
--------
.. autosummary::
:toctree: api/
GeoSeries.plot
GeoSeries.explore
Spatial index
-------------
.. autosummary::
:toctree: api/
GeoSeries.sindex
GeoSeries.has_sindex
Indexing
--------
.. autosummary::
:toctree: api/
GeoSeries.cx
Interface
---------
.. autosummary::
:toctree: api/
GeoSeries.__geo_interface__
Methods of pandas ``Series`` objects are also available, although not
all are applicable to geometric objects and some may return a
``Series`` rather than a ``GeoSeries`` result when appropriate. The methods
``isna()`` and ``fillna()`` have been
implemented specifically for ``GeoSeries`` and are expected to work
correctly.
+37
View File
@@ -0,0 +1,37 @@
============
Input/output
============
.. currentmodule:: geopandas
GIS vector files
----------------
.. autosummary::
:toctree: api/
read_file
GeoDataFrame.to_file
PostGIS
-------
.. autosummary::
:toctree: api/
read_postgis
GeoDataFrame.to_postgis
Feather
-------
.. autosummary::
:toctree: api/
read_feather
GeoDataFrame.to_feather
Parquet
-------
.. autosummary::
:toctree: api/
read_parquet
GeoDataFrame.to_parquet
+52
View File
@@ -0,0 +1,52 @@
=============
Spatial index
=============
.. currentmodule:: geopandas
GeoPandas offers built-in support for spatial indexing using an R-Tree algorithm.
Depending on the ability to import ``pygeos``, GeoPandas will either use
``pygeos.STRtree`` or ``rtree.index.Index``. The main interface for both is the
same and follows the ``pygeos`` model.
``GeoSeries.sindex`` creates a spatial index, which can use the methods and
properties documented below.
Constructor
-----------
.. autosummary::
:toctree: api/
GeoSeries.sindex
Spatial Index object
--------------------
The spatial index object returned from :attr:`GeoSeries.sindex` has the following
methods:
.. currentmodule:: geopandas.sindex.SpatialIndex
.. autosummary::
:toctree: api/
intersection
is_empty
nearest
query
query_bulk
size
valid_query_predicates
The concrete implementations currently available are
``geopandas.sindex.PyGEOSSTRTreeIndex`` and ``geopandas.sindex.RTreeIndex``.
In addition to the methods listed above, the ``rtree``-based spatial index
(``geopandas.sindex.RTreeIndex``) offers the full capability of
``rtree.index.Index`` - see the full API in the `rtree documentation`_.
Similarly, the ``pygeos``-based spatial index
(``geopandas.sindex.PyGEOSSTRTreeIndex``) offers the full capability of
``pygeos.STRtree``, including nearest-neighbor queries.
See the full API in the `PyGEOS STRTree documentation`_.
.. _rtree documentation: https://rtree.readthedocs.io/en/stable/class.html
.. _PyGEOS STRTree documentation: https://pygeos.readthedocs.io/en/latest/strtree.html
+14
View File
@@ -0,0 +1,14 @@
=======
Testing
=======
.. currentmodule:: geopandas
GeoPandas includes specific functions to test its objects.
.. autosummary::
:toctree: api/
.. testing.geom_equals
.. testing.geom_almost_equals
testing.assert_geoseries_equal
testing.assert_geodataframe_equal
+18
View File
@@ -0,0 +1,18 @@
=====
Tools
=====
.. currentmodule:: geopandas
.. autosummary::
:toctree: api/
sjoin
sjoin_nearest
overlay
clip
tools.geocode
tools.reverse_geocode
tools.collect
points_from_xy
datasets.available
datasets.get_path
+23
View File
@@ -0,0 +1,23 @@
User Guide
==========
The User Guide covers different parts of basic usage of GeoPandas. Each page focuses on a single topic and outlines how it is implemented in GeoPandas, with reproducible examples.
If you don't know anything about GeoPandas, start with the :doc:`Introduction to GeoPandas <../getting_started/introduction>`.
Advanced topics can be found in the :doc:`Advanced Guide <advanced_guide>` and further specification in the :doc:`API Reference <reference>`.
.. toctree::
:maxdepth: 2
Data Structures <user_guide/data_structures>
Reading and Writing Files <user_guide/io>
Indexing and Selecting Data <user_guide/indexing>
Making Maps and plots <user_guide/mapping>
Interactive mapping <user_guide/interactive_mapping>
Managing Projections <user_guide/projections>
Geometric Manipulations <user_guide/geometric_manipulations>
Set Operations with overlay <user_guide/set_operations>
Aggregation with dissolve <user_guide/aggregation_with_dissolve>
Merging Data <user_guide/mergingdata>
Geocoding <user_guide/geocoding>
@@ -12,17 +12,21 @@ Aggregation with dissolve
Spatial data are often more granular than we need. For example, we might have data on sub-national units, but we're actually interested in studying patterns at the level of countries.
In a non-spatial setting, when all we need are summary statistics of the data, we aggregate our data using the ``groupby`` function. But for spatial data, we sometimes also need to aggregate geometric features. In the *geopandas* library, we can aggregate geometric features using the ``dissolve`` function.
In a non-spatial setting, when all we need are summary statistics of the data, we aggregate our data using the :meth:`~pandas.DataFrame.groupby` function. But for spatial data, we sometimes also need to aggregate geometric features. In the *geopandas* library, we can aggregate geometric features using the :meth:`~geopandas.GeoDataFrame.dissolve` function.
``dissolve`` can be thought of as doing three things: (a) it dissolves all the geometries within a given group together into a single geometric feature (using the ``unary_union`` method), and (b) it aggregates all the rows of data in a group using ``groupby.aggregate()``, and (c) it combines those two results.
:meth:`~geopandas.GeoDataFrame.dissolve` can be thought of as doing three things:
``dissolve`` Example
~~~~~~~~~~~~~~~~~~~~~
(a) it dissolves all the geometries within a given group together into a single geometric feature (using the :attr:`~geopandas.GeoSeries.unary_union` method), and
(b) it aggregates all the rows of data in a group using :ref:`groupby.aggregate <groupby.aggregate>`, and
(c) it combines those two results.
:meth:`~geopandas.GeoDataFrame.dissolve` Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suppose we are interested in studying continents, but we only have country-level data like the country dataset included in *geopandas*. We can easily convert this to a continent-level dataset.
First, let's look at the most simple case where we just want continent shapes and names. By default, ``dissolve`` will pass ``'first'`` to ``groupby.aggregate``.
First, let's look at the most simple case where we just want continent shapes and names. By default, :meth:`~geopandas.GeoDataFrame.dissolve` will pass ``'first'`` to :ref:`groupby.aggregate <groupby.aggregate>`.
.. ipython:: python
@@ -35,7 +39,7 @@ First, let's look at the most simple case where we just want continent shapes an
continents.head()
If we are interested in aggregate populations, however, we can pass different functions to the ``dissolve`` method to aggregate populations using the ``aggfunc =`` argument:
If we are interested in aggregate populations, however, we can pass different functions to the :meth:`~geopandas.GeoDataFrame.dissolve` method to aggregate populations using the ``aggfunc =`` argument:
.. ipython:: python
@@ -62,7 +66,7 @@ Dissolve Arguments
~~~~~~~~~~~~~~~~~~
The ``aggfunc =`` argument defaults to 'first' which means that the first row of attributes values found in the dissolve routine will be assigned to the resultant dissolved geodataframe.
However it also accepts other summary statistic options as allowed by ``pandas.groupby()`` including:
However it also accepts other summary statistic options as allowed by :meth:`pandas.groupby <pandas.DataFrame.groupby>` including:
* 'first'
* 'last'
@@ -71,3 +75,25 @@ However it also accepts other summary statistic options as allowed by ``pandas.g
* 'sum'
* 'mean'
* 'median'
* function
* string function name
* list of functions and/or function names, e.g. [np.sum, 'mean']
* dict of axis labels -> functions, function names or list of such.
For example, to get the number of contries on each continent,
as well as the populations of the largest and smallest country of each,
we can aggregate the ``'name'`` column using ``'count'``,
and the ``'pop_est'`` column using ``'min'`` and ``'max'``:
.. ipython:: python
world = geopandas.read_file(geopandas.datasets.get_path("naturalearth_lowres"))
continents = world.dissolve(
by="continent",
aggfunc={
"name": "count",
"pop_est": ["min", "max"],
},
)
continents.head()
@@ -14,8 +14,8 @@ Data Structures
=========================================
GeoPandas implements two main data structures, a :class:`GeoSeries` and a
:class:`GeoDataFrame`. These are subclasses of pandas ``Series`` and
``DataFrame``, respectively.
:class:`GeoDataFrame`. These are subclasses of :class:`pandas.Series` and
:class:`pandas.DataFrame`, respectively.
GeoSeries
---------
@@ -45,10 +45,10 @@ operation is carried out elementwise. The two series will be aligned
by matching indices. Binary operations can also be applied to a
single geometry, in which case the operation is carried out for each
element of the series with that geometry. In either case, a
``Series`` or a :class:`GeoSeries` will be returned, as appropriate.
:class:`~pandas.Series` or a :class:`GeoSeries` will be returned, as appropriate.
A short summary of a few attributes and methods for GeoSeries is
presented here, and a full list can be found in the :doc:`all attributes and methods page <reference>`.
presented here, and a full list can be found in the :doc:`all attributes and methods page <../reference/geoseries>`.
There is also a family of methods for creating new shapes by expanding
existing shapes or applying set-theoretic operations like "union" described
in :doc:`geometric manipulations <geometric_manipulations>`.
@@ -64,7 +64,7 @@ Attributes
Basic Methods
^^^^^^^^^^^^^^
* :meth:`~GeoSeries.distance`: returns ``Series`` with minimum distance from each entry to ``other``
* :meth:`~GeoSeries.distance`: returns :class:`~pandas.Series` with minimum distance from each entry to ``other``
* :attr:`~GeoSeries.centroid`: returns :class:`GeoSeries` of centroids
* :meth:`~GeoSeries.representative_point`: returns :class:`GeoSeries` of points that are guaranteed to be within each geometry. It does **NOT** return centroids.
* :meth:`~GeoSeries.to_crs`: change coordinate reference system. See :doc:`projections <projections>`
@@ -117,6 +117,7 @@ We can also rename this column to "borders":
Now, we create centroids and make it the geometry:
.. ipython:: python
:okwarning:
world['centroid_column'] = world.centroid
world = world.set_geometry('centroid_column')
@@ -129,14 +130,14 @@ Now, we create centroids and make it the geometry:
gdf = gdf.rename(columns={'old_name': 'new_name'}).set_geometry('new_name')
**Note 2:** Somewhat confusingly, by default when you use the ``read_file`` command, the column containing spatial objects from the file is named "geometry" by default, and will be set as the active geometry column. However, despite using the same term for the name of the column and the name of the special attribute that keeps track of the active column, they are distinct. You can easily shift the active geometry column to a different :class:`GeoSeries` with the :meth:`~GeoDataFrame.set_geometry` command. Further, ``gdf.geometry`` will always return the active geometry column, *not* the column named ``geometry``. If you wish to call a column named "geometry", and a different column is the active geometry column, use ``gdf['geometry']``, not ``gdf.geometry``.
**Note 2:** Somewhat confusingly, by default when you use the :func:`~geopandas.read_file` command, the column containing spatial objects from the file is named "geometry" by default, and will be set as the active geometry column. However, despite using the same term for the name of the column and the name of the special attribute that keeps track of the active column, they are distinct. You can easily shift the active geometry column to a different :class:`GeoSeries` with the :meth:`~GeoDataFrame.set_geometry` command. Further, ``gdf.geometry`` will always return the active geometry column, *not* the column named ``geometry``. If you wish to call a column named "geometry", and a different column is the active geometry column, use ``gdf['geometry']``, not ``gdf.geometry``.
Attributes and Methods
~~~~~~~~~~~~~~~~~~~~~~
Any of the attributes calls or methods described for a :class:`GeoSeries` will work on a :class:`GeoDataFrame` -- effectively, they are just applied to the "geometry" :class:`GeoSeries`.
However, ``GeoDataFrames`` also have a few extra methods for input and output which are described on the :doc:`Input and Output <io>` page and for geocoding with are described in :doc:`Geocoding <geocoding>`.
However, :class:`GeoDataFrames <GeoDataFrame>` also have a few extra methods for input and output which are described on the :doc:`Input and Output <io>` page and for geocoding with are described in :doc:`Geocoding <geocoding>`.
.. ipython:: python
@@ -157,7 +158,7 @@ option to control:
geopandas.options
The ``geopandas.options.display_precision`` option can control the number of
decimals to show in the display of coordinates in the geometry column.
decimals to show in the display of coordinates in the geometry column.
In the ``world`` example of above, the default is to show 5 decimals for
geographic coordinates:
@@ -32,17 +32,17 @@ with the detailed borough boundary file included within ``geopandas``.
boro_locations.plot(ax=ax, color="red");
By default, the ``geocode`` function uses the
`GeoCode.Farm geocoding API <https://geocode.farm/>`__ with a rate limitation
applied. But a different geocoding service can be specified with the
By default, the :func:`~geopandas.tools.geocode` function uses the
`Photon geocoding API <https://photon.komoot.io>`__.
But a different geocoding service can be specified with the
``provider`` keyword.
The argument to ``provider`` can either be a string referencing geocoding
services, such as ``'google'``, ``'bing'``, ``'yahoo'``, and
``'openmapquest'``, or an instance of a ``Geocoder`` from ``geopy``. See
``'openmapquest'``, or an instance of a :mod:`Geocoder <geopy.geocoders>` from :mod:`geopy`. See
``geopy.geocoders.SERVICE_TO_GEOCODER`` for the full list.
For many providers, parameters such as API keys need to be passed as
``**kwargs`` in the ``geocode`` call.
``**kwargs`` in the :func:`~geopandas.tools.geocode` call.
For example, to use the OpenStreetMap Nominatim geocoder, you need to specify
a user agent:
@@ -54,6 +54,6 @@ a user agent:
.. attention::
Please consult the Terms of Service for the chosen provider. The example
above uses ``'geocodefarm'`` (the default), for which free users are
limited to 250 calls per day and 4 requests per second
(`geocodefarm ToS <https://geocode.farm/geocoding/free-api-documentation/>`_).
above uses ``'photon'`` (the default), which expects fair usage
- extensive usage will be throttled.
(`Photon's Terms of Use <https://photon.komoot.io>`_).
@@ -3,7 +3,7 @@
Geometric Manipulations
========================
*geopandas* makes available all the tools for geometric manipulations in the `*shapely* library <http://shapely.readthedocs.io/en/latest/manual.html>`_.
*geopandas* makes available all the tools for geometric manipulations in the `shapely library <http://shapely.readthedocs.io/en/latest/manual.html>`_.
Note that documentation for all set-theoretic tools for creating new shapes using the relationship between two different spatial datasets -- like creating intersections, or differences -- can be found on the :doc:`set operations <set_operations>` page.
@@ -12,39 +12,39 @@ Constructive Methods
.. method:: GeoSeries.buffer(distance, resolution=16)
Returns a ``GeoSeries`` of geometries representing all points within a given `distance`
Returns a :class:`~geopandas.GeoSeries` of geometries representing all points within a given `distance`
of each geometric object.
.. attribute:: GeoSeries.boundary
Returns a ``GeoSeries`` of lower dimensional objects representing
Returns a :class:`~geopandas.GeoSeries` of lower dimensional objects representing
each geometries's set-theoretic `boundary`.
.. attribute:: GeoSeries.centroid
Returns a ``GeoSeries`` of points for each geometric centroid.
Returns a :class:`~geopandas.GeoSeries` of points for each geometric centroid.
.. attribute:: GeoSeries.convex_hull
Returns a ``GeoSeries`` of geometries representing the smallest
Returns a :class:`~geopandas.GeoSeries` of geometries representing the smallest
convex `Polygon` containing all the points in each object unless the
number of points in the object is less than three. For two points,
the convex hull collapses to a `LineString`; for 1, a `Point`.
.. attribute:: GeoSeries.envelope
Returns a ``GeoSeries`` of geometries representing the point or
Returns a :class:`~geopandas.GeoSeries` of geometries representing the point or
smallest rectangular polygon (with sides parallel to the coordinate
axes) that contains each object.
.. method:: GeoSeries.simplify(tolerance, preserve_topology=True)
Returns a ``GeoSeries`` containing a simplified representation of
Returns a :class:`~geopandas.GeoSeries` containing a simplified representation of
each object.
.. attribute:: GeoSeries.unary_union
Return a geometry containing the union of all geometries in the ``GeoSeries``.
Return a geometry containing the union of all geometries in the :class:`~geopandas.GeoSeries`.
Affine transformations
@@ -52,23 +52,23 @@ Affine transformations
.. method:: GeoSeries.affine_transform(self, matrix)
Transform the geometries of the GeoSeries using an affine transformation matrix
Transform the geometries of the :class:`~geopandas.GeoSeries` using an affine transformation matrix
.. method:: GeoSeries.rotate(self, angle, origin='center', use_radians=False)
Rotate the coordinates of the GeoSeries.
Rotate the coordinates of the :class:`~geopandas.GeoSeries`.
.. method:: GeoSeries.scale(self, xfact=1.0, yfact=1.0, zfact=1.0, origin='center')
Scale the geometries of the GeoSeries along each (x, y, z) dimensio.
Scale the geometries of the :class:`~geopandas.GeoSeries` along each (x, y, z) dimension.
.. method:: GeoSeries.skew(self, angle, origin='center', use_radians=False)
Shear/Skew the geometries of the GeoSeries by angles along x and y dimensions.
Shear/Skew the geometries of the :class:`~geopandas.GeoSeries` by angles along x and y dimensions.
.. method:: GeoSeries.translate(self, xoff=0.0, yoff=0.0, zoff=0.0)
Shift the coordinates of the GeoSeries.
Shift the coordinates of the :class:`~geopandas.GeoSeries`.
@@ -90,9 +90,9 @@ Examples of Geometric Manipulations
2 POLYGON ((2 0, 3 0, 3 1, 2 1, 2 0))
dtype: geometry
.. image:: _static/test.png
.. image:: ../../_static/test.png
Some geographic operations return normal pandas object. The ``area`` property of a ``GeoSeries`` will return a ``pandas.Series`` containing the area of each item in the ``GeoSeries``:
Some geographic operations return normal pandas object. The :attr:`~geopandas.GeoSeries.area` property of a :class:`~geopandas.GeoSeries` will return a :class:`pandas.Series` containing the area of each item in the :class:`~geopandas.GeoSeries`:
.. sourcecode:: python
@@ -112,9 +112,9 @@ Other operations return GeoPandas objects:
2 POLYGON ((1.5 0, 1.5 1, 1.502407636663901 1.04...
dtype: geometry
.. image:: _static/test_buffer.png
.. image:: ../../_static/test_buffer.png
GeoPandas objects also know how to plot themselves. GeoPandas uses `descartes`_ to generate a `matplotlib`_ plot. To generate a plot of our GeoSeries, use:
GeoPandas objects also know how to plot themselves. GeoPandas uses `matplotlib`_ for plotting. To generate a plot of our GeoSeries, use:
.. sourcecode:: python
@@ -130,22 +130,22 @@ GeoPandas also implements alternate constructors that can read any data format r
>>> boros.sort_index(inplace=True)
>>> boros
BoroName Shape_Leng Shape_Area \
BoroCode
1 Manhattan 359299.096471 6.364715e+08
2 Bronx 464392.991824 1.186925e+09
3 Brooklyn 741080.523166 1.937479e+09
4 Queens 896344.047763 3.045213e+09
5 Staten Island 330470.010332 1.623820e+09
geometry
BoroCode
1 MULTIPOLYGON (((981219.0557861328 188655.31579...
2 MULTIPOLYGON (((1012821.805786133 229228.26458...
3 MULTIPOLYGON (((1021176.479003906 151374.79699...
4 MULTIPOLYGON (((1029606.076599121 156073.81420...
5 MULTIPOLYGON (((970217.0223999023 145643.33221...
BoroCode
1 Manhattan 359299.096471 6.364715e+08
2 Bronx 464392.991824 1.186925e+09
3 Brooklyn 741080.523166 1.937479e+09
4 Queens 896344.047763 3.045213e+09
5 Staten Island 330470.010332 1.623820e+09
.. image:: _static/nyc.png
geometry
BoroCode
1 MULTIPOLYGON (((981219.0557861328 188655.31579...
2 MULTIPOLYGON (((1012821.805786133 229228.26458...
3 MULTIPOLYGON (((1021176.479003906 151374.79699...
4 MULTIPOLYGON (((1029606.076599121 156073.81420...
5 MULTIPOLYGON (((970217.0223999023 145643.33221...
.. image:: ../../_static/nyc.png
.. sourcecode:: python
@@ -158,10 +158,10 @@ GeoPandas also implements alternate constructors that can read any data format r
5 POLYGON ((915517.6877458114 120121.8812543372,...
dtype: geometry
.. image:: _static/nyc_hull.png
.. image:: ../../_static/nyc_hull.png
To demonstrate a more complex operation, we'll generate a
``GeoSeries`` containing 2000 random points:
:class:`~geopandas.GeoSeries` containing 2000 random points:
.. sourcecode:: python
@@ -178,7 +178,7 @@ Now draw a circle with fixed radius around each point:
>>> circles = pts.buffer(2000)
We can collapse these circles into a single shapely MultiPolygon
We can collapse these circles into a single :class:`MultiPolygon`
geometry with
.. sourcecode:: python
@@ -192,7 +192,7 @@ just use:
>>> holes = boros['geometry'].intersection(mp)
.. image:: _static/holes.png
.. image:: ../../_static/holes.png
and to get the area outside of the holes:
@@ -200,11 +200,11 @@ and to get the area outside of the holes:
>>> boros_with_holes = boros['geometry'].difference(mp)
.. image:: _static/boros_with_holes.png
.. image:: ../../_static/boros_with_holes.png
Note that this can be simplified a bit, since ``geometry`` is
available as an attribute on a ``GeoDataFrame``, and the
``intersection`` and ``difference`` methods are implemented with the
available as an attribute on a :class:`~geopandas.GeoDataFrame`, and the
:meth:`~geopandas.GeoSeries.intersection` and :meth:`~geopandas.GeoSeries.difference` methods are implemented with the
"&" and "-" operators, respectively. For example, the latter could
have been expressed simply as ``boros.geometry - mp``.
@@ -222,7 +222,6 @@ borough that are in the holes:
5 0.558075
dtype: float64
.. _Descartes: https://pypi.python.org/pypi/descartes
.. _matplotlib: http://matplotlib.org
.. _fiona: http://fiona.readthedocs.io/en/latest/
.. _geopy: https://github.com/geopy/geopy
+29
View File
@@ -0,0 +1,29 @@
.. currentmodule:: geopandas
.. ipython:: python
:suppress:
import geopandas
Indexing and Selecting Data
===========================
GeoPandas inherits the standard pandas_ methods for indexing/selecting data. This includes label based indexing with :attr:`~pandas.DataFrame.loc` and integer position based indexing with :attr:`~pandas.DataFrame.iloc`, which apply to both :class:`GeoSeries` and :class:`GeoDataFrame` objects. For more information on indexing/selecting, see the pandas_ documentation.
.. _pandas: http://pandas.pydata.org/pandas-docs/stable/indexing.html
In addition to the standard pandas_ methods, GeoPandas also provides
coordinate based indexing with the :attr:`~GeoDataFrame.cx` indexer, which slices using a bounding
box. Geometries in the :class:`GeoSeries` or :class:`GeoDataFrame` that intersect the
bounding box will be returned.
Using the ``world`` dataset, we can use this functionality to quickly select all
countries whose boundaries extend into the southern hemisphere.
.. ipython:: python
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
southern_world = world.cx[:, :0]
@savefig world_southern.png
southern_world.plot(figsize=(10, 3));
@@ -0,0 +1,149 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "c554e753",
"metadata": {},
"source": [
"# Interactive mapping\n",
"\n",
"Alongside static plots, `geopandas` can create interactive maps based on the [folium](https://python-visualization.github.io/folium/) library.\n",
"\n",
"Creating maps for interactive exploration mirrors the API of [static plots](../reference/api/geopandas.GeoDataFrame.plot.html) in an [explore()](../reference/api/geopandas.GeoDataFrame.explore.html) method of a GeoSeries or GeoDataFrame.\n",
"\n",
"Loading some example data:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "caf2fbd5",
"metadata": {},
"outputs": [],
"source": [
"import geopandas\n",
"\n",
"nybb = geopandas.read_file(geopandas.datasets.get_path('nybb'))\n",
"world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))\n",
"cities = geopandas.read_file(geopandas.datasets.get_path('naturalearth_cities'))"
]
},
{
"cell_type": "markdown",
"id": "56bf1bcf",
"metadata": {},
"source": [
"The simplest option is to use `GeoDataFrame.explore()`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6b484ecc",
"metadata": {},
"outputs": [],
"source": [
"nybb.explore()"
]
},
{
"cell_type": "markdown",
"id": "7a797389",
"metadata": {},
"source": [
"Interactive plotting offers largely the same customisation as static one plus some features on top of that. Check the code below which plots a customised choropleth map. You can use `\"BoroName\"` column with NY boroughs names as an input of the choropleth, show (only) its name in the tooltip on hover but show all values on click. You can also pass custom background tiles (either a name supported by folium, a name recognized by `xyzservices.providers.query_name()`, XYZ URL or `xyzservices.TileProvider` object), specify colormap (all supported by `matplotlib`) and specify black outline."
]
},
{
"cell_type": "markdown",
"id": "798bf532",
"metadata": {},
"source": [
"<div class=\"alert alert-info\">\n",
"Note\n",
"\n",
"Note that the GeoDataFrame needs to have a CRS set if you want to use background tiles.\n",
"</div>"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "94b4ff24",
"metadata": {},
"outputs": [],
"source": [
"nybb.explore( \n",
" column=\"BoroName\", # make choropleth based on \"BoroName\" column\n",
" tooltip=\"BoroName\", # show \"BoroName\" value in tooltip (on hover)\n",
" popup=True, # show all values in popup (on click)\n",
" tiles=\"CartoDB positron\", # use \"CartoDB positron\" tiles\n",
" cmap=\"Set1\", # use \"Set1\" matplotlib colormap\n",
" style_kwds=dict(color=\"black\") # use black outline\n",
" )"
]
},
{
"cell_type": "markdown",
"id": "5a10291e",
"metadata": {},
"source": [
"The `explore()` method returns a `folium.Map` object, which can also be passed directly (as you do with `ax` in `plot()`). You can then use folium functionality directly on the resulting map. In the example below, you can plot two GeoDataFrames on the same map and add layer control using folium. You can also add additional tiles allowing you to change the background directly in the map."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cba9970b",
"metadata": {},
"outputs": [],
"source": [
"import folium\n",
"\n",
"m = world.explore(\n",
" column=\"pop_est\", # make choropleth based on \"BoroName\" column\n",
" scheme=\"naturalbreaks\", # use mapclassify's natural breaks scheme\n",
" legend=True, # show legend\n",
" k=10, # use 10 bins\n",
" legend_kwds=dict(colorbar=False), # do not use colorbar\n",
" name=\"countries\" # name of the layer in the map\n",
")\n",
"\n",
"cities.explore(\n",
" m=m, # pass the map object\n",
" color=\"red\", # use red color on all points\n",
" marker_kwds=dict(radius=10, fill=True), # make marker radius 10px with fill\n",
" tooltip=\"name\", # show \"name\" column in the tooltip\n",
" tooltip_kwds=dict(labels=False), # do not show column label in the tooltip\n",
" name=\"cities\" # name of the layer in the map\n",
")\n",
"\n",
"folium.TileLayer('Stamen Toner', control=True).add_to(m) # use folium to add alternative tiles\n",
"folium.LayerControl().add_to(m) # use folium to add layer control\n",
"\n",
"m # show map"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -1,28 +1,36 @@
.. _io:
Reading and Writing Files
=========================================
=========================
Reading Spatial Data
---------------------
*geopandas* can read almost any vector-based spatial data format including ESRI shapefile, GeoJSON files and more using the command::
*geopandas* can read almost any vector-based spatial data format including ESRI
shapefile, GeoJSON files and more using the command::
geopandas.read_file()
which returns a GeoDataFrame object. (This is possible because *geopandas* makes use of the great `fiona <http://fiona.readthedocs.io/en/latest/manual.html>`_ library, which in turn makes use of a massive open-source program called `GDAL/OGR <http://www.gdal.org/>`_ designed to facilitate spatial data transformations).
which returns a GeoDataFrame object. This is possible because *geopandas* makes
use of the great `fiona <http://fiona.readthedocs.io/en/latest/manual.html>`_
library, which in turn makes use of a massive open-source program called
`GDAL/OGR <http://www.gdal.org/>`_ designed to facilitate spatial data
transformations.
Any arguments passed to :func:`geopandas.read_file` after the file name will be passed directly to ``fiona.open``, which does the actual data importation. In general, :func:`geopandas.read_file` is pretty smart and should do what you want without extra arguments, but for more help, type::
Any arguments passed to :func:`geopandas.read_file` after the file name will be
passed directly to :func:`fiona.open`, which does the actual data importation. In
general, :func:`geopandas.read_file` is pretty smart and should do what you want
without extra arguments, but for more help, type::
import fiona; help(fiona.open)
Among other things, one can explicitly set the driver (shapefile, GeoJSON) with the ``driver`` keyword, or pick a single layer from a multi-layered file with the ``layer`` keyword::
Among other things, one can explicitly set the driver (shapefile, GeoJSON) with
the ``driver`` keyword, or pick a single layer from a multi-layered file with
the ``layer`` keyword::
countries_gdf = geopandas.read_file("package.gpkg", layer='countries')
Where supported in ``fiona``, *geopandas* can also load resources directly from
Where supported in :mod:`fiona`, *geopandas* can also load resources directly from
a web URL, for example for GeoJSON files from `geojson.xyz <http://geojson.xyz/>`_::
url = "http://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_110m_land.geojson"
@@ -37,25 +45,32 @@ If the dataset is in a folder in the ZIP file, you have to append its name::
zipfile = "zip:///Users/name/Downloads/gadm36_AFG_shp.zip!data"
If there are multiple datasets in a folder in the ZIP file, you also have to specify the filename::
If there are multiple datasets in a folder in the ZIP file, you also have to
specify the filename::
zipfile = "zip:///Users/name/Downloads/gadm36_AFG_shp.zip!data/gadm36_AFG_1.shp"
It is also possible to read any file-like objects with a ``read()`` method, such as a file handler (e.g. via built-in ``open`` function) or ``StringIO``::
It is also possible to read any file-like objects with a :func:`os.read` method, such
as a file handler (e.g. via built-in :func:`open` function) or :class:`~io.StringIO`::
filename = "test.geojson"
file = open(filename)
df = geopandas.read_file(file)
File-like objects from `fsspec <https://filesystem-spec.readthedocs.io/en/latest>`_
can also be used to read data, allowing for any combination of storage backends and caching
supported by that project::
path = "simplecache::http://download.geofabrik.de/antarctica-latest-free.shp.zip"
with fsspec.open(path) as file:
df = geopandas.read_file(file)
You can also read path objects::
import pathlib
path_object = pathlib.path(filename)
df = geopandas.read_file(path_object)
*geopandas* can also get data from a PostGIS database using the :func:`geopandas.read_postgis` command.
Reading subsets of the data
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -172,9 +187,47 @@ by using the :meth:`geopandas.GeoDataFrame.to_postgis` method.
countries_gdf.to_file("package.gpkg", layer='countries', driver="GPKG")
cities_gdf.to_file("package.gpkg", layer='cities', driver="GPKG")
**Writing to PostGIS**::
Spatial databases
-----------------
*geopandas* can also get data from a PostGIS database using the
:func:`geopandas.read_postgis` command.
Writing to PostGIS::
from sqlalchemy import create_engine
db_connection_url = "postgres://myusername:mypassword@myhost:5432/mydatabase";
db_connection_url = "postgresql://myusername:mypassword@myhost:5432/mydatabase";
engine = create_engine(db_connection_url)
countries_gdf.to_postgis(name="countries_table", con=engine)
countries_gdf.to_postgis("countries_table", con=engine)
Apache Parquet and Feather file formats
---------------------------------------
.. versionadded:: 0.8.0
GeoPandas supports writing and reading the Apache Parquet and Feather file
formats.
`Apache Parquet <https://parquet.apache.org/>`__ is an efficient, columnar
storage format (originating from the Hadoop ecosystem). It is a widely used
binary file format for tabular data. The Feather file format is the on-disk
representation of the `Apache Arrow <https://arrow.apache.org/>`__ memory
format, an open standard for in-memory columnar data.
The :func:`geopandas.read_parquet`, :func:`geopandas.read_feather`,
:meth:`GeoDataFrame.to_parquet` and :meth:`GeoDataFrame.to_feather` methods
enable fast roundtrip from GeoPandas to those binary file formats, preserving
the spatial information.
.. warning::
This is an initial implementation of Parquet file support and
associated metadata. This is tracking version 0.1.0 of the metadata
specification at:
https://github.com/geopandas/geo-arrow-spec
This metadata specification does not yet make stability promises. As such,
we do not yet recommend using this in a production setting unless you are
able to rewrite your Parquet or Feather files.
@@ -11,11 +11,13 @@
plt.close('all')
Mapping Tools
Mapping and Plotting Tools
=========================================
*geopandas* provides a high-level interface to the ``matplotlib`` library for making maps. Mapping shapes is as easy as using the ``plot()`` method on a ``GeoSeries`` or ``GeoDataFrame``.
*geopandas* provides a high-level interface to the matplotlib_ library for making maps. Mapping shapes is as easy as using the :meth:`~GeoDataFrame.plot()` method on a :class:`GeoSeries` or :class:`GeoDataFrame`.
.. _matplotlib: https://matplotlib.org/stable/
Loading some example data:
@@ -35,7 +37,7 @@ We can now plot those GeoDataFrames:
@savefig world_randomcolors.png
world.plot();
Note that in general, any options one can pass to `pyplot <http://matplotlib.org/api/pyplot_api.html>`_ in ``matplotlib`` (or `style options that work for lines <http://matplotlib.org/api/lines_api.html>`_) can be passed to the ``plot()`` method.
Note that in general, any options one can pass to `pyplot <http://matplotlib.org/api/pyplot_api.html>`_ in matplotlib_ (or `style options that work for lines <http://matplotlib.org/api/lines_api.html>`_) can be passed to the :meth:`~GeoDataFrame.plot` method.
Choropleth Maps
@@ -44,8 +46,9 @@ Choropleth Maps
*geopandas* makes it easy to create Choropleth maps (maps where the color of each shape is based on the value of an associated variable). Simply use the plot command with the ``column`` argument set to the column whose values you want used to assign colors.
.. ipython:: python
:okwarning:
# Plot by GDP per capta
# Plot by GDP per capita
world = world[(world.pop_est>0) & (world.name!="Antarctica")]
world['gdp_per_cap'] = world.gdp_md_est / world.pop_est
@savefig world_gdp_per_cap.png
@@ -65,7 +68,7 @@ When plotting a map, one can enable a legend using the ``legend`` argument:
@savefig world_pop_est.png
world.plot(column='pop_est', ax=ax, legend=True)
However, the default appearance of the legend and plot axes may not be desirable. One can define the plot axes (with ``ax``) and the legend axes (with ``cax``) and then pass those in to the ``plot`` call. The following example uses ``mpl_toolkits`` to vertically align the plot axes and the legend axes:
However, the default appearance of the legend and plot axes may not be desirable. One can define the plot axes (with ``ax``) and the legend axes (with ``cax``) and then pass those in to the :meth:`~GeoDataFrame.plot` call. The following example uses ``mpl_toolkits`` to vertically align the plot axes and the legend axes:
.. ipython:: python
@@ -96,7 +99,7 @@ And the following example plots the color bar below the map and adds its label u
Choosing colors
~~~~~~~~~~~~~~~~
One can also modify the colors used by ``plot`` with the ``cmap`` option (for a full list of colormaps, see the `matplotlib website <http://matplotlib.org/users/colormaps.html>`_):
One can also modify the colors used by :meth:`~GeoDataFrame.plot` with the ``cmap`` option (for a full list of colormaps, see the `matplotlib website <http://matplotlib.org/users/colormaps.html>`_):
.. ipython:: python
@@ -113,7 +116,7 @@ To make the color transparent for when you just want to show the boundary, you h
The way color maps are scaled can also be manipulated with the ``scheme`` option (if you have ``mapclassify`` installed, which can be accomplished via ``conda install -c conda-forge mapclassify``). The ``scheme`` option can be set to any scheme provided by mapclassify (e.g. 'box_plot', 'equal_interval',
'fisher_jenks', 'fisher_jenks_sampled', 'headtail_breaks', 'jenks_caspall', 'jenks_caspall_forced', 'jenks_caspall_sampled', 'max_p_classifier', 'maximum_breaks', 'natural_breaks', 'quantiles', 'percentiles', 'std_mean' or 'user_defined'). Arguments can be passed in classification_kwds dict. See the `mapclassify documentation <https://mapclassify.readthedocs.io>`_ for further details about these map classification schemes.
'fisher_jenks', 'fisher_jenks_sampled', 'headtail_breaks', 'jenks_caspall', 'jenks_caspall_forced', 'jenks_caspall_sampled', 'max_p_classifier', 'maximum_breaks', 'natural_breaks', 'quantiles', 'percentiles', 'std_mean' or 'user_defined'). Arguments can be passed in classification_kwds dict. See the `mapclassify documentation <https://pysal.org/mapclassify>`_ for further details about these map classification schemes.
.. ipython:: python
@@ -154,6 +157,17 @@ However, passing ``missing_kwds`` one can specify the style and label of feature
},
);
Other map customizations
~~~~~~~~~~~~~~~~~~~~~~~~
Maps usually do not have to have axis labels. You can turn them off using ``set_axis_off()`` or ``axis("off")`` axis methods.
.. ipython:: python
ax = world.plot()
@savefig set_axis_off.png
ax.set_axis_off();
Maps with Layers
-----------------
@@ -222,6 +236,41 @@ We can set the ``zorder`` for cities higher than for world to move it of top.
@savefig zorder_set.png
world.plot(ax=ax, zorder=1);
Pandas Plots
-----------------
Plotting methods also allow for different plot styles from pandas
along with the default ``geo`` plot. These methods can be accessed using
the ``kind`` keyword argument in :meth:`~GeoDataFrame.plot`, and include:
* ``geo`` for mapping
* ``line`` for line plots
* ``bar`` or ``barh`` for bar plots
* ``hist`` for histogram
* ``box`` for boxplot
* ``kde`` or ``density`` for density plots
* ``area`` for area plots
* ``scatter`` for scatter plots
* ``hexbin`` for hexagonal bin plots
* ``pie`` for pie plots
.. ipython:: python
gdf = world.head(10)
@savefig pandas_line_plot.png
gdf.plot(kind='scatter', x="pop_est", y="gdp_md_est")
You can also create these other plots using the ``GeoDataFrame.plot.<kind>`` accessor methods instead of providing the ``kind`` keyword argument.
.. ipython:: python
@savefig pandas_bar_plot.png
gdf.plot.bar()
For more information check out the `pandas documentation <https://pandas.pydata.org/pandas-docs/stable/user_guide/visualization.html>`_.
Other Resources
-----------------
Links to jupyter Notebooks for different mapping tasks:
+162
View File
@@ -0,0 +1,162 @@
.. currentmodule:: geopandas
.. ipython:: python
:suppress:
import geopandas
Merging Data
=========================================
There are two ways to combine datasets in *geopandas* -- attribute joins and spatial joins.
In an attribute join, a :class:`GeoSeries` or :class:`GeoDataFrame` is
combined with a regular :class:`pandas.Series` or :class:`pandas.DataFrame` based on a
common variable. This is analogous to normal merging or joining in *pandas*.
In a Spatial Join, observations from two :class:`GeoSeries` or :class:`GeoDataFrame`
are combined based on their spatial relationship to one another.
In the following examples, we use these datasets:
.. ipython:: python
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
cities = geopandas.read_file(geopandas.datasets.get_path('naturalearth_cities'))
# For attribute join
country_shapes = world[['geometry', 'iso_a3']]
country_names = world[['name', 'iso_a3']]
# For spatial join
countries = world[['geometry', 'name']]
countries = countries.rename(columns={'name':'country'})
Appending
---------
Appending :class:`GeoDataFrame` and :class:`GeoSeries` uses pandas :meth:`~pandas.DataFrame.append` methods.
Keep in mind, that appended geometry columns needs to have the same CRS.
.. ipython:: python
# Appending GeoSeries
joined = world.geometry.append(cities.geometry)
# Appending GeoDataFrames
europe = world[world.continent == 'Europe']
asia = world[world.continent == 'Asia']
eurasia = europe.append(asia)
Attribute Joins
----------------
Attribute joins are accomplished using the :meth:`~pandas.DataFrame.merge` method. In general, it is recommended
to use the ``merge()`` method called from the spatial dataset. With that said, the stand-alone
:func:`pandas.merge` function will work if the :class:`GeoDataFrame` is in the ``left`` argument;
if a :class:`~pandas.DataFrame` is in the ``left`` argument and a :class:`GeoDataFrame`
is in the ``right`` position, the result will no longer be a :class:`GeoDataFrame`.
For example, consider the following merge that adds full names to a :class:`GeoDataFrame`
that initially has only ISO codes for each country by merging it with a :class:`~pandas.DataFrame`.
.. ipython:: python
# `country_shapes` is GeoDataFrame with country shapes and iso codes
country_shapes.head()
# `country_names` is DataFrame with country names and iso codes
country_names.head()
# Merge with `merge` method on shared variable (iso codes):
country_shapes = country_shapes.merge(country_names, on='iso_a3')
country_shapes.head()
Spatial Joins
----------------
In a Spatial Join, two geometry objects are merged based on their spatial relationship to one another.
.. ipython:: python
# One GeoDataFrame of countries, one of Cities.
# Want to merge so we can get each city's country.
countries.head()
cities.head()
# Execute spatial join
cities_with_country = cities.sjoin(countries, how="inner", predicate='intersects')
cities_with_country.head()
GeoPandas provides two spatial-join functions:
- :meth:`GeoDataFrame.sjoin`: joins based on binary predicates (intersects, contains, etc.)
- :meth:`GeoDataFrame.sjoin_nearest`: joins based on proximity, with the ability to set a maximum search radius.
.. note::
For historical reasons, both methods are also available as top-level functions :func:`sjoin` and :func:`sjoin_nearest`.
It is recommended to use methods as the functions may be deprecated in the future.
Binary Predicate Joins
~~~~~~~~~~~~~~~~~~~~~~
Binary predicate joins are available via :meth:`GeoDataFrame.sjoin`.
:meth:`GeoDataFrame.sjoin` has two core arguments: ``how`` and ``predicate``.
**predicate**
The ``predicate`` argument specifies how ``geopandas`` decides whether or not to join the attributes of one
object to another, based on their geometric relationship.
The values for ``predicate`` correspond to the names of geometric binary predicates and depend on the spatial
index implementation.
The default spatial index in ``geopandas`` currently supports the following values for ``predicate`` which are
defined in the
`Shapely documentation <http://shapely.readthedocs.io/en/latest/manual.html#binary-predicates>`__:
* `intersects`
* `contains`
* `within`
* `touches`
* `crosses`
* `overlaps`
**how**
The `how` argument specifies the type of join that will occur and which geometry is retained in the resultant
:class:`GeoDataFrame`. It accepts the following options:
* ``left``: use the index from the first (or `left_df`) :class:`GeoDataFrame` that you provide
to :meth:`GeoDataFrame.sjoin`; retain only the `left_df` geometry column
* ``right``: use index from second (or `right_df`); retain only the `right_df` geometry column
* ``inner``: use intersection of index values from both :class:`GeoDataFrame`; retain only the `left_df` geometry column
Note more complicated spatial relationships can be studied by combining geometric operations with spatial join.
To find all polygons within a given distance of a point, for example, one can first use the :meth:`~geopandas.GeoSeries.buffer` method to expand each
point into a circle of appropriate radius, then intersect those buffered circles with the polygons in question.
Nearest Joins
~~~~~~~~~~~~~
Proximity-based joins can be done via :meth:`GeoDataFrame.sjoin_nearest`.
:meth:`GeoDataFrame.sjoin_nearest` shares the ``how`` argument with :meth:`GeoDataFrame.sjoin`, and
includes two additional arguments: ``max_distance`` and ``distance_col``.
**max_distance**
The ``max_distance`` argument specifies a maximum search radius for matching geometries. This can have a considerable performance impact in some cases.
If you can, it is highly recommended that you use this parameter.
**distance_col**
If set, the resultant GeoDataFrame will include a column with this name containing the computed distances between an input geometry and the nearest geometry.
@@ -22,7 +22,7 @@ empty geometries:
a Shapely geometry object.
- **Missing geometries** are unknown values in a GeoSeries. They will typically
be propagated in operations (for example in calculations of the area or of
the intersection), or ignored in reductions such as ``unary_union``.
the intersection), or ignored in reductions such as :attr:`~GeoSeries.unary_union`.
The scalar object (when accessing a single element of a GeoSeries) is the
Python ``None`` object.
@@ -67,7 +67,7 @@ you can use the :attr:`GeoSeries.is_empty` attribute:
s.is_empty
To get only the actual geometry objects that are neiter missing nor empty,
To get only the actual geometry objects that are neither missing nor empty,
you can use a combination of both:
.. ipython:: python
@@ -160,7 +160,7 @@ Consider the following small toy example:
.. code-block:: python
>>> s1.intersection(s2)
>>> s1.intersection(s2)
0 GEOMETRYCOLLECTION EMPTY
1 POINT (1 1)
2 GEOMETRYCOLLECTION EMPTY
@@ -169,7 +169,7 @@ Consider the following small toy example:
* Starting from GeoPandas v0.6.0, :meth:`GeoSeries.align` will use missing
values to fill in the non-aligned indices, to be consistent with the
behaviour in pandas:
.. ipython:: python
s1_aligned, s2_aligned = s1.align(s2)
@@ -181,5 +181,6 @@ Consider the following small toy example:
depending on the spatial operation:
.. ipython:: python
:okwarning:
s1.intersection(s2)
@@ -30,7 +30,7 @@ referred to using the authority code ``"EPSG:4326"``.
- CRS WKT string
- An authority string (i.e. "epsg:4326")
- An EPSG integer code (i.e. 4326)
- A ``pyproj.CRS``
- A :class:`pyproj.CRS <pyproj.crs.CRS>`
- An object with a to_wkt method.
- PROJ string
- Dictionary of PROJ parameters
@@ -71,7 +71,7 @@ the :attr:`GeoSeries.crs` attribute):
.. sourcecode:: python
my_geoseries = my_geoseries.set_crs("EPSG:4326"})
my_geoseries = my_geoseries.set_crs("EPSG:4326")
my_geoseries = my_geoseries.set_crs(epsg=4326)
@@ -86,7 +86,7 @@ Re-projecting is the process of changing the representation of locations from on
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
# Check original projection
# (it's Platte Carre! x-y are long and lat)
# (it's Plate Carrée! x-y are long and lat)
world.crs
# Visualize
@@ -109,8 +109,8 @@ GeoPandas 0.8 implements support for different projections assigned to different
columns of the same GeoDataFrame. The projection is now stored together with geometries per column (directly
on the GeometryArray level).
Note that if GeometryArray has assigned projection, it is preferred over the
projection passed to GeoSeries or GeoDataFrame during the creation:
Note that if GeometryArray has an assigned projection, it cannot be overridden by an another inconsistent
projection during the creation of a GeoSeries or GeoDataFrame:
.. code-block:: python
@@ -121,18 +121,12 @@ projection passed to GeoSeries or GeoDataFrame during the creation:
- Lat[north]: Geodetic latitude (degree)
- Lon[east]: Geodetic longitude (degree)
...
>>> GeoSeries(array, crs=3395).crs # crs=3395 is ignored as array already has CRS
FutureWarning: CRS mismatch between CRS of the passed geometries and 'crs'. Use 'GeoDataFrame.set_crs(crs, allow_override=True)' to overwrite CRS or 'GeoDataFrame.to_crs(crs)' to reproject geometries. CRS mismatch will raise an error in the future versions of GeoPandas.
>>> GeoSeries(array, crs=4326) # crs=4326 is okay, as it matches the existing CRS
>>> GeoSeries(array, crs=3395) # crs=3395 is forbidden as array already has CRS
ValueError: CRS mismatch between CRS of the passed geometries and 'crs'. Use 'GeoSeries.set_crs(crs, allow_override=True)' to overwrite CRS or 'GeoSeries.to_crs(crs)' to reproject geometries.
GeoSeries(array, crs=3395).crs
<Geographic 2D CRS: EPSG:4326>
Name: WGS 84
Axis Info [ellipsoidal]:
- Lat[north]: Geodetic latitude (degree)
- Lon[east]: Geodetic longitude (degree)
...
If you want to overwrite projection, you can then assign it to the GeoSeries
If you want to overwrite the projection, you can then assign it to the GeoSeries
manually or re-project geometries to the target projection using either
``GeoSeries.set_crs(epsg=3395, allow_override=True)`` or
``GeoSeries.to_crs(epsg=3395)``.
@@ -145,7 +139,7 @@ Upgrading to GeoPandas 0.7 with pyproj > 2.2 and PROJ > 6
---------------------------------------------------------
Starting with GeoPandas 0.7, the `.crs` attribute of a GeoSeries or GeoDataFrame
stores the CRS information as a ``pyproj.CRS``, and no longer as a proj4 string
stores the CRS information as a :class:`pyproj.CRS <pyproj.crs.CRS>`, and no longer as a proj4 string
or dict.
Before, you might have seen this:
@@ -176,7 +170,7 @@ for some more background, and the subsections below cover different possible
migration issues.
See the `pyproj docs <https://pyproj4.github.io/pyproj/stable/>`__ for more on
the ``pyproj.CRS`` object.
the :class:`pyproj.CRS <pyproj.crs.CRS>` object.
Importing data from files
^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -240,7 +234,7 @@ For example, instead of:
gdf.crs = "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs"
we recommenend to do:
we recommend to do:
.. code-block:: python
@@ -267,11 +261,11 @@ including their EPSG codes and proj4 string definitions.
**Other formats**
Next to the EPSG code mentioned above, there are also other ways to specify the
CRS: an actual ``pyproj.CRS`` object, a WKT string, a PROJ JSON string, etc.
Anything that is accepted by ``pyproj.CRS.from_user_input`` can by specified
CRS: an actual :class:`pyproj.CRS <pyproj.crs.CRS>` object, a WKT string, a PROJ JSON string, etc.
Anything that is accepted by :meth:`pyproj.CRS.from_user_input() <pyproj.crs.CRS.from_user_input>` can by specified
to the ``crs`` keyword/attribute in GeoPandas.
Also compatible CRS objects, such as from the ``rasterio`` package, can be
Also compatible CRS objects, such as from the :mod:`rasterio` package, can be
passed directly to GeoPandas.
@@ -306,7 +300,7 @@ Why is it not properly recognizing my CRS?
There are many file sources and CRS definitions out there "in the wild" that
might have a CRS description that does not fully conform to the new standards of
PROJ > 6 (proj4 strings, older WKT formats, ...). In such cases, you will get a
``pyproj.CRS`` object that might not be fully what you expected (e.g. not equal
:class:`pyproj.CRS <pyproj.crs.CRS>` object that might not be fully what you expected (e.g. not equal
to the expected EPSG code). Below we list a few possible cases.
I get a "Bound CRS"?
@@ -447,7 +441,7 @@ The ``.crs`` attribute is no longer a dict or string
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you relied on the ``.crs`` object being a dict or a string, such code can
be broken given it is now a ``pyproj.CRS`` object. But this object actually
be broken given it is now a :class:`pyproj.CRS <pyproj.crs.CRS>` object. But this object actually
provides a more robust interface to get information about the CRS.
For example, if you used the following code to get the EPSG code:
@@ -457,7 +451,7 @@ For example, if you used the following code to get the EPSG code:
gdf.crs['init']
This will no longer work. To get the EPSG code from a ``crs`` object, you can use
the ``to_epsg()`` method.
the :meth:`~pyproj.crs.CRS.to_epsg` method.
Or to check if a CRS was a certain UTM zone:
@@ -465,11 +459,11 @@ Or to check if a CRS was a certain UTM zone:
'+proj=utm ' in gdf.crs
could be replaced with the longer but more robust check:
could be replaced with the more robust check (requires pyproj 2.6+):
.. code-block:: python
gdf.crs.is_projected and gdf.crs.coordinate_operation.name.upper().startswith('UTM')
gdf.crs.utm_zone is not None
And there are many other methods available on the ``pyproj.CRS`` class to get
And there are many other methods available on the :class:`pyproj.CRS <pyproj.crs.CRS>` class to get
information about the CRS.
@@ -0,0 +1,87 @@
Re-projecting using GDAL with Rasterio and Fiona
================================================
The simplest method of re-projecting is :meth:`GeoDataFrame.to_crs`.
It uses ``pyproj`` as the engine and transforms the points within the geometries.
These examples demonstrate how to use ``Fiona`` or ``rasterio`` as the engine to re-project your data.
Fiona and rasterio are powered by GDAL and with algorithms that consider the geometry instead of
just the points the geometry contains. This is particularly useful for antimeridian cutting.
However, this also means the transformation is not as fast.
Fiona Example
-------------
.. code-block:: python
from functools import partial
import fiona
import geopandas
from fiona.transform import transform_geom
from packaging import version
from pyproj import CRS
from pyproj.enums import WktVersion
from shapely.geometry import mapping, shape
# set up Fiona transformer
def crs_to_fiona(proj_crs):
proj_crs = CRS.from_user_input(proj_crs)
if version.parse(fiona.__gdal_version__) < version.parse("3.0.0"):
fio_crs = proj_crs.to_wkt(WktVersion.WKT1_GDAL)
else:
# GDAL 3+ can use WKT2
fio_crs = proj_crs.to_wkt()
return fio_crs
def base_transformer(geom, src_crs, dst_crs):
return shape(
transform_geom(
src_crs=crs_to_fiona(src_crs),
dst_crs=crs_to_fiona(dst_crs),
geom=mapping(geom),
antimeridian_cutting=True,
)
)
# load example data
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
destination_crs = "EPSG:3395"
forward_transformer = partial(base_transformer, src_crs=world.crs, dst_crs=destination_crs)
# Reproject to Mercator (after dropping Antartica)
world = world[(world.name != "Antarctica") & (world.name != "Fr. S. Antarctic Lands")]
with fiona.Env(OGR_ENABLE_PARTIAL_REPROJECTION="YES"):
mercator_world = world.set_geometry(world.geometry.apply(forward_transformer), crs=destination_crs)
Rasterio Example
----------------
This example requires rasterio 1.2+ and GDAL 3+.
.. code-block:: python
import geopandas
import rasterio.warp
from shapely.geometry import shape
# load example data
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
# Reproject to Mercator (after dropping Antartica)
world = world[(world.name != "Antarctica") & (world.name != "Fr. S. Antarctic Lands")]
destination_crs = "EPSG:3395"
geometry = rasterio.warp.transform_geom(
src_crs=world.crs,
dst_crs=destination_crs,
geom=world.geometry.values,
)
mercator_world = world.set_geometry(
[shape(geom) for geom in geometry],
crs=destination_crs,
)
@@ -1,3 +1,5 @@
.. currentmodule:: geopandas
.. ipython:: python
:suppress:
@@ -14,22 +16,23 @@ When working with multiple spatial datasets -- especially multiple *polygon* or
those datasets overlap (or don't overlap). These manipulations are often
referred using the language of sets -- intersections, unions, and differences.
These types of operations are made available in the *geopandas* library through
the ``overlay`` function.
the :meth:`~geopandas.GeoDataFrame.overlay` method.
The basic idea is demonstrated by the graphic below but keep in mind that
overlays operate at the DataFrame level, not on individual geometries, and the
properties from both are retained. In effect, for every shape in the first
GeoDataFrame, this operation is executed against every other shape in the other
GeoDataFrame:
properties from both are retained. In effect, for every shape in the left
:class:`~geopandas.GeoDataFrame`, this operation is executed against every other shape in the right
:class:`~geopandas.GeoDataFrame`:
.. image:: _static/overlay_operations.png
.. image:: ../../_static/overlay_operations.png
**Source: QGIS Documentation**
(Note to users familiar with the *shapely* library: ``overlay`` can be thought
of as offering versions of the standard *shapely* set-operations that deal with
the complexities of applying set operations to two *GeoSeries*. The standard
*shapely* set-operations are also available as ``GeoSeries`` methods.)
.. note::
Note to users familiar with the *shapely* library: :meth:`~geopandas.GeoDataFrame.overlay` can be thought
of as offering versions of the standard *shapely* set-operations that deal with
the complexities of applying set operations to two *GeoSeries*. The standard
*shapely* set-operations are also available as :class:`~geopandas.GeoSeries` methods.
The different Overlay operations
@@ -57,16 +60,20 @@ These two GeoDataFrames have some overlapping areas:
df2.plot(ax=ax, color='green', alpha=0.5);
We illustrate the different overlay modes with the above example.
The ``overlay`` function will determine the set of all individual geometries
The :meth:`~geopandas.GeoDataFrame.overlay` method will determine the set of all individual geometries
from overlaying the two input GeoDataFrames. This result covers the area covered
by the two input GeoDataFrames, and also preserves all unique regions defined by
the combined boundaries of the two GeoDataFrames.
.. note::
For historical reasons, the overlay method is also available as a top-level function :func:`overlay`.
It is recommended to use the method as the function may be deprecated in the future.
When using ``how='union'``, all those possible geometries are returned:
.. ipython:: python
res_union = geopandas.overlay(df1, df2, how='union')
res_union = df1.overlay(df2, how='union')
res_union
ax = res_union.plot(alpha=0.5, cmap='tab10')
@@ -80,7 +87,7 @@ by both GeoDataFrames:
.. ipython:: python
res_intersection = geopandas.overlay(df1, df2, how='intersection')
res_intersection = df1.overlay(df2, how='intersection')
res_intersection
ax = res_intersection.plot(cmap='tab10')
@@ -93,7 +100,7 @@ the geometries that are only part of one of the GeoDataFrames but not of both:
.. ipython:: python
res_symdiff = geopandas.overlay(df1, df2, how='symmetric_difference')
res_symdiff = df1.overlay(df2, how='symmetric_difference')
res_symdiff
ax = res_symdiff.plot(cmap='tab10')
@@ -106,7 +113,7 @@ To obtain the geometries that are part of ``df1`` but are not contained in
.. ipython:: python
res_difference = geopandas.overlay(df1, df2, how='difference')
res_difference = df1.overlay(df2, how='difference')
res_difference
ax = res_difference.plot(cmap='tab10')
@@ -119,7 +126,7 @@ but with the geometries obtained from overlaying ``df1`` with ``df2``:
.. ipython:: python
res_identity = geopandas.overlay(df1, df2, how='identity')
res_identity = df1.overlay(df2, how='identity')
res_identity
ax = res_identity.plot(cmap='tab10')
@@ -138,7 +145,7 @@ First, we load the countries and cities example datasets and select :
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
capitals = geopandas.read_file(geopandas.datasets.get_path('naturalearth_cities'))
# Select South Amarica and some columns
# Select South America and some columns
countries = world[world['continent'] == "South America"]
countries = countries[['geometry', 'name']]
@@ -146,7 +153,7 @@ First, we load the countries and cities example datasets and select :
countries = countries.to_crs('epsg:3395')
capitals = capitals.to_crs('epsg:3395')
To illustrate the ``overlay`` function, consider the following case in which one
To illustrate the :meth:`~geopandas.GeoDataFrame.overlay` method, consider the following case in which one
wishes to identify the "core" portion of each country -- defined as areas within
500km of a capital -- using a ``GeoDataFrame`` of countries and a
``GeoDataFrame`` of capitals.
@@ -171,7 +178,7 @@ To select only the portion of countries within 500km of a capital, we specify th
.. ipython:: python
country_cores = geopandas.overlay(countries, capitals, how='intersection')
country_cores = countries.overlay(capitals, how='intersection')
@savefig country_cores.png width=5in
country_cores.plot(alpha=0.5, edgecolor='k', cmap='tab10');
@@ -179,7 +186,7 @@ Changing the "how" option allows for different types of overlay operations. For
.. ipython:: python
country_peripheries = geopandas.overlay(countries, capitals, how='difference')
country_peripheries = countries.overlay(capitals, how='difference')
@savefig country_peripheries.png width=5in
country_peripheries.plot(alpha=0.5, edgecolor='k', cmap='tab10');
@@ -194,7 +201,7 @@ Changing the "how" option allows for different types of overlay operations. For
keep_geom_type keyword
----------------------
In default settings, ``overlay`` returns only geometries of the same geometry type as df1
In default settings, :meth:`~geopandas.GeoDataFrame.overlay` returns only geometries of the same geometry type as GeoDataFrame
(left one) has, where Polygon and MultiPolygon is considered as a same type (other types likewise).
You can control this behavior using ``keep_geom_type`` option, which is set to
True by default. Once set to False, ``overlay`` will return all geometry types resulting from
@@ -205,7 +212,7 @@ where two polygons intersects in a line or a point.
More Examples
-------------
A larger set of examples of the use of ``overlay`` can be found `here <http://nbviewer.jupyter.org/github/geopandas/geopandas/blob/master/examples/overlays.ipynb>`_
A larger set of examples of the use of :meth:`~geopandas.GeoDataFrame.overlay` can be found `here <https://nbviewer.jupyter.org/github/geopandas/geopandas/blob/main/doc/source/gallery/overlays.ipynb>`_
+232
View File
@@ -0,0 +1,232 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Plotting with CartoPy and GeoPandas\n",
"\n",
"Converting between GeoPandas and CartoPy for visualizing data.\n",
"\n",
"[CartoPy](http://scitools.org.uk/cartopy/) is a Python library\n",
"that specializes in creating geospatial\n",
"visualizations. It has a slightly different way of representing\n",
"Coordinate Reference Systems (CRS) as well as constructing plots.\n",
"This example steps through a round-trip transfer of data\n",
"between GeoPandas and CartoPy.\n",
"\n",
"First we'll load in the data using GeoPandas.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import geopandas\n",
"from cartopy import crs as ccrs\n",
"\n",
"path = geopandas.datasets.get_path('naturalearth_lowres')\n",
"df = geopandas.read_file(path)\n",
"# Add a column we'll use later\n",
"df['gdp_pp'] = df['gdp_md_est'] / df['pop_est']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First we'll visualize the map using GeoPandas\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df.plot()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Plotting with CartoPy\n",
"=====================\n",
"\n",
"Cartopy also handles Shapely objects well, but it uses a different system for\n",
"CRS. To plot this data with CartoPy, we'll first need to project it into a\n",
"new CRS. We'll use a CRS defined within CartoPy and use the GeoPandas\n",
"``to_crs`` method to make the transformation.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Define the CartoPy CRS object.\n",
"crs = ccrs.AzimuthalEquidistant()\n",
"\n",
"# This can be converted into a `proj4` string/dict compatible with GeoPandas\n",
"crs_proj4 = crs.proj4_init\n",
"df_ae = df.to_crs(crs_proj4)\n",
"\n",
"# Here's what the plot looks like in GeoPandas\n",
"df_ae.plot()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that our data is in a CRS based off of CartoPy, we can easily\n",
"plot it.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(subplot_kw={'projection': crs})\n",
"ax.add_geometries(df_ae['geometry'], crs=crs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that we could have easily done this with an EPSG code like so:\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"crs_epsg = ccrs.epsg('3857')\n",
"df_epsg = df.to_crs(epsg='3857')\n",
"\n",
"# Generate a figure with two axes, one for CartoPy, one for GeoPandas\n",
"fig, axs = plt.subplots(1, 2, subplot_kw={'projection': crs_epsg},\n",
" figsize=(10, 5))\n",
"# Make the CartoPy plot\n",
"axs[0].add_geometries(df_epsg['geometry'], crs=crs_epsg,\n",
" facecolor='white', edgecolor='black')\n",
"# Make the GeoPandas plot\n",
"df_epsg.plot(ax=axs[1], color='white', edgecolor='black')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"CartoPy to GeoPandas\n",
"====================\n",
"\n",
"Next we'll perform a CRS projection in CartoPy, and then convert it\n",
"back into a GeoPandas object.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"crs_new = ccrs.AlbersEqualArea()\n",
"new_geometries = [crs_new.project_geometry(ii, src_crs=crs)\n",
" for ii in df_ae['geometry'].values]\n",
"\n",
"fig, ax = plt.subplots(subplot_kw={'projection': crs_new})\n",
"ax.add_geometries(new_geometries, crs=crs_new)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that we've created new Shapely objects with the CartoPy CRS,\n",
"we can use this to create a GeoDataFrame.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_aea = geopandas.GeoDataFrame(df['gdp_pp'], geometry=new_geometries,\n",
" crs=crs_new.proj4_init)\n",
"df_aea.plot()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can even combine these into the same figure. Here we'll plot the\n",
"shapes of the countries with CartoPy. We'll then calculate the centroid\n",
"of each with GeoPandas and plot it on top.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"nbsphinx-thumbnail"
]
},
"outputs": [],
"source": [
"# Generate a CartoPy figure and add the countries to it\n",
"fig, ax = plt.subplots(subplot_kw={'projection': crs_new})\n",
"ax.add_geometries(new_geometries, crs=crs_new)\n",
"\n",
"# Calculate centroids and plot\n",
"df_aea_centroids = df_aea.geometry.centroid\n",
"# Need to provide \"zorder\" to ensure the points are plotted above the polygons\n",
"df_aea_centroids.plot(ax=ax, markersize=5, color='r', zorder=10)\n",
"\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,228 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Creating a GeoDataFrame from a DataFrame with coordinates\n",
"\n",
"This example shows how to create a ``GeoDataFrame`` when starting from\n",
"a *regular* ``DataFrame`` that has coordinates either WKT\n",
"([well-known text](https://en.wikipedia.org/wiki/Well-known_text))\n",
"format, or in\n",
"two columns.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import geopandas\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"From longitudes and latitudes\n",
"=============================\n",
"\n",
"First, let's consider a ``DataFrame`` containing cities and their respective\n",
"longitudes and latitudes.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df = pd.DataFrame(\n",
" {'City': ['Buenos Aires', 'Brasilia', 'Santiago', 'Bogota', 'Caracas'],\n",
" 'Country': ['Argentina', 'Brazil', 'Chile', 'Colombia', 'Venezuela'],\n",
" 'Latitude': [-34.58, -15.78, -33.45, 4.60, 10.48],\n",
" 'Longitude': [-58.66, -47.91, -70.66, -74.08, -66.86]})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A ``GeoDataFrame`` needs a ``shapely`` object. We use geopandas\n",
"``points_from_xy()`` to transform **Longitude** and **Latitude** into a list\n",
"of ``shapely.Point`` objects and set it as a ``geometry`` while creating the\n",
"``GeoDataFrame``. (note that ``points_from_xy()`` is an enhanced wrapper for\n",
"``[Point(x, y) for x, y in zip(df.Longitude, df.Latitude)]``)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gdf = geopandas.GeoDataFrame(\n",
" df, geometry=geopandas.points_from_xy(df.Longitude, df.Latitude))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"``gdf`` looks like this :\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(gdf.head())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we plot the coordinates over a country-level map.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"nbsphinx-thumbnail"
]
},
"outputs": [],
"source": [
"world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))\n",
"\n",
"# We restrict to South America.\n",
"ax = world[world.continent == 'South America'].plot(\n",
" color='white', edgecolor='black')\n",
"\n",
"# We can now plot our ``GeoDataFrame``.\n",
"gdf.plot(ax=ax, color='red')\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"From WKT format\n",
"===============\n",
"Here, we consider a ``DataFrame`` having coordinates in WKT format.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df = pd.DataFrame(\n",
" {'City': ['Buenos Aires', 'Brasilia', 'Santiago', 'Bogota', 'Caracas'],\n",
" 'Country': ['Argentina', 'Brazil', 'Chile', 'Colombia', 'Venezuela'],\n",
" 'Coordinates': ['POINT(-58.66 -34.58)', 'POINT(-47.91 -15.78)',\n",
" 'POINT(-70.66 -33.45)', 'POINT(-74.08 4.60)',\n",
" 'POINT(-66.86 10.48)']})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We use ``shapely.wkt`` sub-module to parse wkt format:\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from shapely import wkt\n",
"\n",
"df['Coordinates'] = geopandas.GeoSeries.from_wkt(df['Coordinates'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The ``GeoDataFrame`` is constructed as follows :\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gdf = geopandas.GeoDataFrame(df, geometry='Coordinates')\n",
"\n",
"print(gdf.head())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Again, we can plot our ``GeoDataFrame``.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ax = world[world.continent == 'South America'].plot(\n",
" color='white', edgecolor='black')\n",
"\n",
"gdf.plot(ax=ax, color='red')\n",
"\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
@@ -0,0 +1,173 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Using GeoPandas with Rasterio to sample point data\n",
"\n",
"This example shows how to use GeoPandas with Rasterio. [Rasterio](https://rasterio.readthedocs.io/en/latest/index.html) is a package for reading and writing raster data.\n",
"\n",
"In this example a set of vector points is used to sample raster data at those points.\n",
"\n",
"The raster data used is Copernicus Sentinel data 2018 for Sentinel data.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import geopandas\n",
"import rasterio\n",
"import matplotlib.pyplot as plt\n",
"from shapely.geometry import Point"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Create example vector data\n",
"=============================\n",
"\n",
"Generate a geodataframe from a set of points\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create sampling points\n",
"points = [Point(625466, 5621289), Point(626082, 5621627), Point(627116, 5621680), Point(625095, 5622358)]\n",
"gdf = geopandas.GeoDataFrame([1, 2, 3, 4], geometry=points, crs=32630)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The ``GeoDataFrame`` looks like this:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gdf.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Open the raster data\n",
"=============================\n",
"\n",
"Use ``rasterio`` to open the raster data to be sampled"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"src = rasterio.open('s2a_l2a_fishbourne.tif')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's see the raster data with the point data overlaid.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"nbsphinx-thumbnail"
]
},
"outputs": [],
"source": [
"from rasterio.plot import show\n",
"\n",
"fig, ax = plt.subplots()\n",
"\n",
"# transform rasterio plot to real world coords\n",
"extent=[src.bounds[0], src.bounds[2], src.bounds[1], src.bounds[3]]\n",
"ax = rasterio.plot.show(src, extent=extent, ax=ax, cmap='pink')\n",
"\n",
"gdf.plot(ax=ax)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sampling the data\n",
"===============\n",
"Rasterio requires a list of the coordinates in x,y format rather than as the points that are in the geomentry column.\n",
"\n",
"This can be achieved using the code below"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"coord_list = [(x,y) for x,y in zip(gdf['geometry'].x , gdf['geometry'].y)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Carry out the sampling of the data and store the results in a new column called `value`. Note that if the image has more than one band, a value is returned for each band."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gdf['value'] = [x for x in src.sample(coord_list)]\n",
"gdf.head()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+11
View File
@@ -0,0 +1,11 @@
Examples Gallery
================
The following examples show off the functionality in GeoPandas. They highlight many of the things you can do with this package, and show off some best-practices.
.. nbgallery::
:name: nbshpinx-gallery
:glob:
./*
@@ -0,0 +1,217 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Adding a scale bar to a matplotlib plot\n",
"When making a geospatial plot in matplotlib, you can use [maplotlib-scalebar library](https://pypi.org/project/matplotlib-scalebar/) to add a scale bar."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import geopandas as gpd\n",
"from matplotlib_scalebar.scalebar import ScaleBar"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Creating a ScaleBar object\n",
"The only required parameter for creating a ScaleBar object is `dx`. This is equal to a size of one pixel in real world. Value of this parameter depends on units of your CRS.\n",
"\n",
"### Projected coordinate system (meters)\n",
"The easiest way to add a scale bar is using a projected coordinate system with meters as units. Just set `dx = 1`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"nbsphinx-thumbnail"
]
},
"outputs": [],
"source": [
"nybb = gpd.read_file(gpd.datasets.get_path('nybb'))\n",
"nybb = nybb.to_crs(32619) # Convert the dataset to a coordinate\n",
"# system which uses meters\n",
"\n",
"ax = nybb.plot()\n",
"ax.add_artist(ScaleBar(1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Geographic coordinate system (degrees)\n",
"With a geographic coordinate system with degrees as units, `dx` should be equal to a distance in meters of two points with the same latitude (Y coordinate) which are one full degree of longitude (X) apart. You can calculate this distance by online calculator [(e.g. the Great Circle calculator)](http://edwilliams.org/gccalc.htm) or in geopandas.\\\n",
"\\\n",
"Firstly, we will create a GeoSeries with two points that have roughly the coordinates of NYC. They are located on the same latitude but one degree of longitude from each other. Their initial coordinates are specified in a geographic coordinate system (geographic WGS 84). They are then converted to a projected system for the calculation:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from shapely.geometry.point import Point\n",
"\n",
"points = gpd.GeoSeries([Point(-73.5, 40.5), Point(-74.5, 40.5)], crs=4326) # Geographic WGS 84 - degrees\n",
"points = points.to_crs(32619) # Projected WGS 84 - meters"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"After the conversion, we can calculate the distance between the points. The result slightly differs from the Great Circle Calculator but the difference is insignificant (84,921 and 84,767 meters):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"distance_meters = points[0].distance(points[1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we are able to use geographic coordinate system in our plot. We set value of `dx` parameter to a distance we just calculated:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"nybb = gpd.read_file(gpd.datasets.get_path('nybb'))\n",
"nybb = nybb.to_crs(4326) # Using geographic WGS 84\n",
"\n",
"ax = nybb.plot()\n",
"ax.add_artist(ScaleBar(distance_meters))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Using other units \n",
"The default unit for `dx` is m (meter). You can change this unit by the `units` and `dimension` parameters. There is a list of some possible `units` for various values of `dimension` below:\n",
"\n",
"| dimension | units |\n",
"| ----- |:-----:|\n",
"| si-length | km, m, cm, um|\n",
"| imperial-length |in, ft, yd, mi|\n",
"|si-length-reciprocal|1/m, 1/cm|\n",
"|angle|deg|\n",
"\n",
"In the following example, we will leave the dataset in its initial CRS which uses feet as units. The plot shows scale of 2 leagues (approximately 11 kilometers):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"nybb = gpd.read_file(gpd.datasets.get_path('nybb'))\n",
"\n",
"ax = nybb.plot()\n",
"ax.add_artist(ScaleBar(1, dimension=\"imperial-length\", units=\"ft\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Customization of the scale bar"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"nybb = gpd.read_file(gpd.datasets.get_path('nybb')).to_crs(32619)\n",
"ax = nybb.plot()\n",
"\n",
"# Position and layout\n",
"scale1 = ScaleBar(\n",
"dx=1, label='Scale 1',\n",
" location='upper left', # in relation to the whole plot\n",
" label_loc='left', scale_loc='bottom' # in relation to the line\n",
")\n",
"\n",
"# Color\n",
"scale2 = ScaleBar(\n",
" dx=1, label='Scale 2', location='center', \n",
" color='#b32400', box_color='yellow',\n",
" box_alpha=0.8 # Slightly transparent box\n",
")\n",
"\n",
"# Font and text formatting\n",
"scale3 = ScaleBar(\n",
" dx=1, label='Scale 3',\n",
" font_properties={'family':'serif', 'size': 'large'}, # For more information, see the cell below\n",
" scale_formatter=lambda value, unit: f'> {value} {unit} <'\n",
")\n",
"\n",
"ax.add_artist(scale1)\n",
"ax.add_artist(scale2)\n",
"ax.add_artist(scale3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*Note:* Font is specified by six properties: `family`, `style`, `variant`, `stretch`, `weight`, `size` (and `math_fontfamily`). See [more](https://matplotlib.org/stable/api/font_manager_api.html#matplotlib.font_manager.FontProperties).\\\n",
"\\\n",
"For more information about matplotlib-scalebar library, see the [PyPI](https://pypi.org/project/matplotlib-scalebar/) or [GitHub](https://github.com/ppinard/matplotlib-scalebar) page."
]
}
],
"metadata": {
"interpreter": {
"hash": "9914e2881520d4f08a067c2c2c181121476026b863eca2e121cd0758701ab602"
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

Before

Width:  |  Height:  |  Size: 320 KiB

After

Width:  |  Height:  |  Size: 320 KiB

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 208 KiB

Some files were not shown because too many files have changed in this diff Show More