Usage#

Get administrative items#

The PyGADM lib can be used to extract information from the GADM dataset as GeoPandas GeoDataFrame.

Countries#

Using the Items class, you can access an administrative area using either its name or its GADM identification code.

For example to extract the France geometry you can use the following code:

import pygadm
from ipyleaflet import GeoJSON, Map, basemaps

gdf = pygadm.Items(name="France")

# display it in a map
m = Map(basemap=basemaps.Esri.WorldImagery,  zoom=5, center=[46.21, 2.21])
m.add(GeoJSON(data=gdf.__geo_interface__, style={"color": "red", "fillOpacity": .4}))

m

If you know the code of the area you try to use, you can use the GADM code instead of the name.

import pygadm
from ipyleaflet import GeoJSON, Map, basemaps

gdf = pygadm.Items(admin="FRA")

# display it in a map
m = Map(basemap=basemaps.Esri.WorldImagery,  zoom=5, center=[46.21, 2.21])
m.add(GeoJSON(data=gdf.__geo_interface__, style={"color": "red", "fillOpacity": .4}))

m

Smaller admin levels#

One is not bind to only request a country, any level can be accessed using both names and/or GADM code.

import pygadm
from ipyleaflet import GeoJSON, Map, basemaps

gdf = pygadm.Items(name="Corse-du-Sud")

# display it in a map
m = Map(basemap=basemaps.Esri.WorldImagery, zoom=8, center=[41.86, 8.97])
m.add(GeoJSON(data=gdf.__geo_interface__, style={"color": "red", "fillOpacity": .4}))

m

Warning

The names of countries are all unique but not the smaller administrative layers. If you request a small area using name, make sure it’s the one you are looking for before running your workflow. follow Duplication issue for more information.

Content of an admin layer#

Using the content_level option, one can require smaller administrative layer than the one setup in the name. For example when you request France, by setting up the content_level option to 2, the geodataframe will include all the department geometries.

import pygadm
from ipyleaflet import GeoJSON, Map, basemaps

gdf = pygadm.Items(admin="FRA", content_level=2)

# display it in a map
m = Map(basemap=basemaps.Esri.WorldImagery,  zoom=5, center=[46.21, 2.21])
m.add(GeoJSON(data=gdf.__geo_interface__, style={"color": "red", "fillOpacity": .4}))

m

Request multiple areas at once#

New in version 0.2.0: names and admin can now be set as list

To perform regional analysis that aggregate multiple boundaries, you can now request them at once using a list of name or a list of admin. In this example we request both germany and France at once:

import pygadm
from ipyleaflet import GeoJSON, Map, basemaps

gdf = pygadm.Items(name=["France", "Germany"])

# display it in a map
m = Map(basemap=basemaps.Esri.WorldImagery,  zoom=5, center=[48.83, 5.17])
m.add(GeoJSON(data=gdf.__geo_interface__, style={"color": "red", "fillOpacity": .4}))

m

Continents#

It’s possible to request all countries from one single continent using one of the following names:

  • North America

  • South America

  • Antartica

  • Europe

  • Asia

  • Oceania

  • Africa

import pygadm
from ipyleaflet import GeoJSON, Map, basemaps

gdf = pygadm.Items(name="south america")

# display it in a map
m = Map(basemap=basemaps.Esri.WorldImagery,  zoom=2, center=[-20.30, -59.32])
m.add(GeoJSON(data=gdf.__geo_interface__, style={"color": "red", "fillOpacity": .4}))

m

Note

it will load all the countries included in the continent. Using it requires a good internet conexion and a powerful computer to handle the produced geoDataFrame. It is suggested to use it without smaller administrative areas.

Find administrative names#

To get the available name and GADM code in a administrative layer you can use the Names class with the same parameters. Use then these names in a Items request to get the geometry.

For example to get the name and codes of all the departments in France you can run:

import pygadm

pygadm.Names(admin="FRA", content_level=2)
NAME_2 GID_2
1 Ain FRA.1.1_1
2 Allier FRA.1.2_1
3 Ardèche FRA.1.3_1
4 Cantal FRA.1.4_1
5 Drôme FRA.1.5_1
... ... ...
92 Alpes-Maritimes FRA.13.2_1
93 Bouches-du-Rhône FRA.13.3_1
94 Hautes-Alpes FRA.13.4_1
95 Var FRA.13.5_1
96 Vaucluse FRA.13.6_1

96 rows × 2 columns

Note

You can also get the list of all the country names by omitting admin and name parameters. If a level is not provided the table will only show country names but other parameters remain availables.

pygadm.Names()

Google Earth engine#

If you want to specifically work within Google Earthengine-api, have a look to pygaul our other library that use the same selection process but return ee.FeatureCollection from the GAUL dataset.

Transform gdf into ee.FeatureCollection#

If you want to use this lib with GEE, install the “earthengine-api” package in your environment and then run the following code and transform the GeoDataFrame into a ee.FeatureCollection as follow:

import pygadm
import ee

ee.Initialize()

gdf = pygadm.Items(name="Corse-du-Sud")

# transform into an ee.FeatureCollection
fc = ee.FeatureCollection(gdf.__geo_interface__)

Simplify geometry#

The GADM dataset are describing the geometry of administrative areas in high-resolution. This may overload the authorized importation limits of earthengine which will lead to the following error:

EEException: Request payload size exceeds the limit: 10485760 bytes.

Use the simplify method from GeoPandas (more information here) to downscale the resolution of the geometries. The following example is needed if you want to work with France:

import pygadm
import geemap
import ee
from ipyleaflet import ZoomControl

ee.Initialize()

gdf = pygadm.Items(name="France")

# reduce resolution
gdf.geometry = gdf.geometry.simplify(tolerance=.001)

# transform into an ee.FeatureCollection
fc = ee.FeatureCollection(gdf.__geo_interface__)

# in this example we use geemap to display the geometry on the map
# the map is customized to have the same look & feel as the rest of the documentation
m = geemap.Map(scroll_wheel_zoom=False, center=[46.21, 2.21], zoom=5, basemap="Esri.WorldImagery")
m.clear_controls()
m.add(ZoomControl())
m.addLayer(fc, {"color": "red"}, "FRA")

m

Duplication issue#

Warning

The names of countries are all unique but not the smaller administrative layers. If you request a small area using name, make sure it’s the one you are looking for before running your workflow. If it’s not the case, use the Names method to get the administrative code associated to the requested names, they are all unique.

Let’s demonstrate this behavior with the “Central” province of Singapore. First we try to load it using its name. It should return an error:

import pygadm

gdf = pygadm.Items(name="Central")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[8], line 3
      1 import pygadm
----> 3 gdf = pygadm.Items(name="Central")

File ~/checkouts/readthedocs.org/user_builds/pygadm/envs/v0.5.3/lib/python3.10/site-packages/pygadm/__init__.py:177, in Items.__init__(self, name, admin, content_level)
    173     names = [""]
    175 # use itertools, normally one of them is empty so it will raise an error
    176 # if not the case as admin and name will be set together
--> 177 gdf_list = [self._items(n, a, content_level) for a, n in product(admins, names)]
    179 # avoid concat if not needed for speed boost
    180 gdf = gdf_list[0] if len(gdf_list) == 1 else pd.concat(gdf_list)

File ~/checkouts/readthedocs.org/user_builds/pygadm/envs/v0.5.3/lib/python3.10/site-packages/pygadm/__init__.py:177, in <listcomp>(.0)
    173     names = [""]
    175 # use itertools, normally one of them is empty so it will raise an error
    176 # if not the case as admin and name will be set together
--> 177 gdf_list = [self._items(n, a, content_level) for a, n in product(admins, names)]
    179 # avoid concat if not needed for speed boost
    180 gdf = gdf_list[0] if len(gdf_list) == 1 else pd.concat(gdf_list)

File ~/checkouts/readthedocs.org/user_builds/pygadm/envs/v0.5.3/lib/python3.10/site-packages/pygadm/__init__.py:199, in Items._items(self, name, admin, content_level)
    197 df = Names(name, admin)
    198 if len(df) > 1:
--> 199     raise ValueError(
    200         f'The requested name ("{name}") is not unique ({len(df)} results). '
    201         'To retrieve it, please use the "admin" parameter instead. '
    202         "If you don't know the GADM code, use the following code, "
    203         f'it will return the GADM codes as well: "Names(name="{name}")"'
    204     )
    205 level = df.columns[0].replace("NAME_", "")
    206 iso_3 = df.iloc[0][f"GID_{level}"][:3]

ValueError: The requested name ("Central") is not unique (9 results). To retrieve it, please use the "admin" parameter instead. If you don't know the GADM code, use the following code, it will return the GADM codes as well: "Names(name="Central")"

As I don’t know the GADM code I copy/paste the suggested code from the error message and filter it by country ISO alpha-3 code. the ISO code is always displayed in the second column of the Names output. All GADM code start with the country ISO code so you can use the provided cell for any admin level.

import pygadm

df = pygadm.Names(name="Central")
df = df[df.iloc[:,1].str.startswith("SGP")]
df
NAME_1 GID_1
6 Central SGP.1_1

I now know that the code is “SGP.1_1” for the Central province so I can run my initial code again with the unique admin parameter:

import pygadm
from ipyleaflet import GeoJSON, Map, basemaps

gdf = pygadm.Items(admin="SGP.1_1")

# display it in a map
m = Map(basemap=basemaps.Esri.WorldImagery,  zoom=11, center=[1.29, 103.83])
m.add(GeoJSON(data=gdf.__geo_interface__, style={"color": "red", "fillOpacity": .4}))

m

Suggestion#

If you make an error when writing the name of your input, the error message will suggest 5 potential candidates in the existing names of the GADM dataset:

import pygadm

gdf = pygadm.Items(name="Franc")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[11], line 3
      1 import pygadm
----> 3 gdf = pygadm.Items(name="Franc")

File ~/checkouts/readthedocs.org/user_builds/pygadm/envs/v0.5.3/lib/python3.10/site-packages/pygadm/__init__.py:177, in Items.__init__(self, name, admin, content_level)
    173     names = [""]
    175 # use itertools, normally one of them is empty so it will raise an error
    176 # if not the case as admin and name will be set together
--> 177 gdf_list = [self._items(n, a, content_level) for a, n in product(admins, names)]
    179 # avoid concat if not needed for speed boost
    180 gdf = gdf_list[0] if len(gdf_list) == 1 else pd.concat(gdf_list)

File ~/checkouts/readthedocs.org/user_builds/pygadm/envs/v0.5.3/lib/python3.10/site-packages/pygadm/__init__.py:177, in <listcomp>(.0)
    173     names = [""]
    175 # use itertools, normally one of them is empty so it will raise an error
    176 # if not the case as admin and name will be set together
--> 177 gdf_list = [self._items(n, a, content_level) for a, n in product(admins, names)]
    179 # avoid concat if not needed for speed boost
    180 gdf = gdf_list[0] if len(gdf_list) == 1 else pd.concat(gdf_list)

File ~/checkouts/readthedocs.org/user_builds/pygadm/envs/v0.5.3/lib/python3.10/site-packages/pygadm/__init__.py:197, in Items._items(self, name, admin, content_level)
    185 """
    186 Return the requested administrative boundaries from the single name or administrative code.
    187 
   (...)
    194     The GeoDataFrame of the requested area with all the GADM attributes.
    195 """
    196 # call to Names without level to raise an error if the requested level won't work
--> 197 df = Names(name, admin)
    198 if len(df) > 1:
    199     raise ValueError(
    200         f'The requested name ("{name}") is not unique ({len(df)} results). '
    201         'To retrieve it, please use the "admin" parameter instead. '
    202         "If you don't know the GADM code, use the following code, "
    203         f'it will return the GADM codes as well: "Names(name="{name}")"'
    204     )

File ~/checkouts/readthedocs.org/user_builds/pygadm/envs/v0.5.3/lib/python3.10/site-packages/pygadm/__init__.py:92, in Names.__init__(self, name, admin, content_level, complete)
     90     else:
     91         close_ids = [i.upper() for i in close_ids]
---> 92     raise ValueError(
     93         f'The requested "{id}" is not part of GADM. '
     94         f'The closest matches are: {", ".join(close_ids)}.'
     95     )
     97 # Get the iso_3 of the associated country of the identifed area and the associated level
     98 line = is_in[~((~is_in).all(axis=1))].idxmax(1)

ValueError: The requested "Franc" is not part of GADM. The closest matches are: Francs, Franco, France, Franca, Francon.