Search code examples
matplotlibgeopandasshapefile

How to assign a colour based on shapefile polygon value?


I am plotting a shapefile over a basemap region. To be specific the column variable "PhytoNAOCo" is plotted on the map. There are some rows (polygons) where the value is 0.00, and I would like to assign a white colour to those polygons, to differentiate it from the others. Here's my code used so far:

pip install geopandas
pip install contextily
import geopandas as gpd
import contextily as ctx

data = gpd.read_file("NAOAMOCorrEcoRegion.shp")
import matplotlib.pyplot as plt
ax=data.plot(figsize=(12,10), column="PhytoNAOCo", legend=True, cmap='bwr')
map = Basemap(llcrnrlon=-50,llcrnrlat=30,urcrnrlon=50.,urcrnrlat=80.,
             resolution='i', lat_0 = 39.5, lon_0 = 1)
map.fillcontinents(color='lightgreen')
map.drawcoastlines()
plt.title("Correlation")

Image

And here's the link to the file - https://drive.google.com/file/d/1VbSYP_kKi8IBSQaDTKjiBYb0PIfA9me9/view?usp=sharing

I guess there would be some kind of loop involved in this case (like if data.PhytoNAOCo(i) == 0, else... then maybe assign a colour?) but I'm new to Python, so I'm not sure how to go about it.


Solution

    • effectively this is covered by geopandas plot missing_kwds
    • hence set rows with zero to NaN then use this inbuilt capability
    import contextily as ctx
    from mpl_toolkits.basemap import Basemap
    import matplotlib.pyplot as plt
    import numpy as np
    
    # data = gpd.read_file("NAOAMOCorrEcoRegion.shp")
    # set 0 to nan
    data.loc[data["PhytoNAOCo"].eq(0), "PhytoNAOCo"] = np.nan
    
    ax = data.plot(
        figsize=(12, 10),
        column="PhytoNAOCo",
        legend=True,
        cmap="bwr",
        missing_kwds={"color":"white"},
    )
    map = Basemap(
        llcrnrlon=-50,
        llcrnrlat=30,
        urcrnrlon=50.0,
        urcrnrlat=80.0,
        resolution="i",
        lat_0=39.5,
        lon_0=1,
    )
    map.fillcontinents(color="lightgreen")
    map.drawcoastlines()
    plt.title("Correlation")
    

    enter image description here

    source data

    from io import BytesIO
    from urllib.request import urlopen
    from zipfile import ZipFile
    from pathlib import Path
    import tempfile
    import geopandas as gpd
    
    # zipurl = 'https://drive.google.com/file/d/1VbSYP_kKi8IBSQaDTKjiBYb0PIfA9me9/view?usp=sharing'
    zipurl = 'https://drive.google.com/uc?export=download&id=1VbSYP_kKi8IBSQaDTKjiBYb0PIfA9me9'
    
    with tempfile.TemporaryDirectory() as d:
        with urlopen(zipurl) as zipresp:
            with ZipFile(BytesIO(zipresp.read())) as zfile:
                zfile.extractall(d)
        data = gpd.read_file(list(Path(d).glob("*.shp"))[0])
    
    
    

    alternative using simple world map for continents

    import matplotlib.pyplot as plt
    import numpy as np
    
    # data = gpd.read_file("NAOAMOCorrEcoRegion.shp")
    # set 0 to nan
    data.loc[data["PhytoNAOCo"].eq(0), "PhytoNAOCo"] = np.nan
    
    ax = data.plot(
        figsize=(12, 10),
        column="PhytoNAOCo",
        legend=True,
        cmap="bwr",
        missing_kwds={"color": "white"},
    )
    ax = (
        gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
        .dissolve() # just want coastlines, so combine all geometries
        .clip_by_rect(*data.total_bounds) # clip to bounds of interesting geometry...
        .plot(color="lightgreen", edgecolor="black", ax=ax)
    )
    
    plt.title("Correlation")
    

    enter image description here