Using the cartopy shapereader

Cartopy provides an object oriented shapefile reader based on top of the pyshp module to provide easy, programmatic, access to standard vector datasets.

Cartopy’s wrapping of pyshp has the benefit of being pure python, and is therefore easy to install and extremely portable. However, for heavy duty shapefile I/O Fiona and GeoPandas are highly recommended.

class cartopy.io.shapereader.Reader(filename)[source]

Provide an interface for accessing the contents of a shapefile.

The primary methods used on a Reader instance are records() and geometries().

geometries()[source]

Return an iterator of shapely geometries from the shapefile.

This interface is useful for accessing the geometries of the shapefile where knowledge of the associated metadata is desired. In the case where further metadata is needed use the records() interface instead, extracting the geometry from the record with the geometry() method.

records()[source]

Return an iterator of Record instances.

class cartopy.io.shapereader.Record(shape, geometry_factory, attributes, fields)[source]

A single logical entry from a shapefile, combining the attributes with their associated geometry.

attributes = None

A dictionary mapping attribute names to attribute values.

bounds

The bounds of this Record’s geometry().

geometry

A shapely.geometry instance for this Record.

The geometry may be None if a null shape is defined in the shapefile.

Helper functions for shapefile acquisition

Cartopy provides an interface for access to frequently used data such as the GSHHS dataset and from the NaturalEarthData website. These interfaces allow the user to define the data programmatically, and if the data does not exist on disk, it will be retrieved from the appropriate source (normally by downloading the data from the internet). Currently the interfaces available are:

cartopy.io.shapereader.natural_earth(resolution='110m', category='physical', name='coastline')[source]

Return the path to the requested natural earth shapefile, downloading and unziping if necessary.

To identify valid components for this function, either browse NaturalEarthData.com, or if you know what you are looking for, go to https://github.com/nvkelso/natural-earth-vector/tree/master/zips to see the actual files which will be downloaded.

Note

Some of the Natural Earth shapefiles have special features which are described in the name. For example, the 110m resolution “admin_0_countries” data also has a sibling shapefile called “admin_0_countries_lakes” which excludes lakes in the country outlines. For details of what is available refer to the Natural Earth website, and look at the “download” link target to identify appropriate names.

cartopy.io.shapereader.gshhs(scale='c', level=1)[source]

Return the path to the requested GSHHS shapefile, downloading and unziping if necessary.

Using the shapereader

We can acquire the countries dataset from Natural Earth found at http://www.naturalearthdata.com/downloads/110m-cultural-vectors/110m-admin-0-countries/ by using the natural_earth() function:

import cartopy.io.shapereader as shpreader

shpfilename = shpreader.natural_earth(resolution='110m',
                                      category='cultural',
                                      name='admin_0_countries')

From here, we can make use of the Reader to get the first country in the shapefile:

reader = shpreader.Reader(shpfilename)
countries = reader.records()
country = next(countries)

We can get the country’s attributes dictionary with the Record.attributes attribute:

>>> print type(country.attributes)
<type 'dict'>
>>> print sorted(country.attributes.keys())
['abbrev', ..., 'name_long', ... 'pop_est', ...]

We could now find the 5 least populated countries with:

reader = shpreader.Reader(shpfilename)

# define a function which returns the population given the country
population = lambda country: country.attributes['pop_est']

# sort the countries by population and get the first 5
countries_by_pop = sorted(reader.records(), key=population)[:5]

Which we can print with

>>> ', '.join([country.attributes['name_long']
...            for country in countries_by_pop])
'Western Sahara, French Southern and Antarctic Lands, Falkland Islands, Antarctica, Greenland'

Exercises:

  • SHP.1: Repeat the last example to show the 4 most populated African countries in to the shapefile.

    Hint: Look at the possible attributes to find out which continent a country belongs.

    Answer:

    Democratic Republic of the Congo, Egypt, Ethiopia, Nigeria
    
  • SHP.2: Using the countries shapefile, find the most populated country grouped by the first letter of the “name_long”.

    Hint: itertools.groupby() can help with the grouping.

    Answer:

    A Argentina
    B Brazil
    C China
    D Democratic Republic of the Congo
    E Ethiopia
    F France
    G Germany
    H Hungary
    I India
    J Japan
    K Kenya
    L Lao PDR
    M Mexico
    N Nigeria
    O Oman
    P Pakistan
    Q Qatar
    R Russian Federation
    S South Africa
    T Turkey
    U United States
    V Vietnam
    W Western Sahara
    Y Yemen
    Z Zimbabwe