Niko Gamulin
Niko Gamulin

Reputation: 66565

How to plot geographic data with customized legend?

Having the geographic points with values, I would like to encode the values with colormap and customize the legend position and colormap range.

Using geopandas, I have written the following function:

def plot_continuous(df, column_values, title):
    fig = plt.figure()
    ax = fig.add_axes([0, 0, 1, 1])
    ax.axis('off')
    df.plot(ax=ax, column=column_values, cmap='OrRd', legend=True);
    ax.title.set_text(title)

The colorbar by default is vertical, but I would like to make it horizontal.

In order to have a horizontal colorbar, I have written the following function:

def plot_continuous(df, column_values, title, legend_title=None):
    fig = plt.figure()
    ax = fig.add_axes([0, 0, 1, 1])
    x = np.array(df.geometry.apply(lambda x: x.x))
    y = np.array(df.geometry.apply(lambda x: x.y))
    vals = np.array(df[column_values])
    sc = ax.scatter(x, y, c=vals, cmap='OrRd')
    cbar = plt.colorbar(sc, orientation="horizontal")
    if legend_title is not None:
        cbar.ax.set_xlabel(legend_title)
    ax.title.set_text(title)

The image width and height in the latter case, however, is not proportional so the output looks distorted.

Does anyone know how to customize the geographic plot and keep the width-height ratio undistorted?

Upvotes: 0

Views: 174

Answers (1)

Rob Raymond
Rob Raymond

Reputation: 31166

This gets far simpler if you use geopandas customisation of plot()

This is documented: https://geopandas.org/en/stable/docs/user_guide/mapping.html

Below I show MWE using your function and then using geopandas. Later has scaled data correctly.

MWE of your code

import geopandas as gpd
import matplotlib.pyplot as plt
import numpy as np

def plot_continuous(df, column_values, title, legend_title=None):
    fig = plt.figure()
    ax = fig.add_axes([0, 0, 1, 1])
    x = np.array(df.geometry.apply(lambda x: x.x))
    y = np.array(df.geometry.apply(lambda x: x.y))
    vals = np.array(df[column_values])
    sc = ax.scatter(x, y, c=vals, cmap='OrRd')
    cbar = plt.colorbar(sc, orientation="horizontal")
    if legend_title is not None:
        cbar.ax.set_xlabel(legend_title)
    ax.title.set_text(title)
    
cities = gpd.read_file(gpd.datasets.get_path("naturalearth_cities"))
cities["color"] = np.random.randint(1,10, len(cities))

plot_continuous(cities, "color", "my title", "Color")

enter image description here

use geopandas

ax = cities.plot(
    column="color",
    cmap="OrRd",
    legend=True,
    legend_kwds={"label": "Color", "orientation": "horizontal"},
)

ax.set_title("my title")

enter image description here

Upvotes: 1

Related Questions