# How to Combine Multiple Maps Using python `multiplot` Function in prettymaps

> Combine multiple maps with Python prettymaps multiplot. Learn to render several geographic regions on one canvas using Subplot objects and custom styling.

- Repository: [Marcelo de Oliveira Rosa Prates/prettymaps](https://github.com/marceloprates/prettymaps)
- Tags: how-to-guide
- Published: 2026-08-20

---

**Use `prettymaps.multiplot()` to render several geographic regions on a single Matplotlib canvas by passing `Subplot` objects that each encapsulate a query and its own styling parameters.**

The **prettymaps** open-source library (marceloprates/prettymaps) generates artistic maps from OpenStreetMap data. While `plot()` produces single-map visualizations, the `multiplot()` function enables composite layouts—ideal for city comparisons, regional surveys, or thematic collections. This guide explains the internal mechanics and practical implementation based on the actual source code.

## Understanding the Multiplot Architecture

### The Three Public Entry Points

In [`prettymaps/__init__.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/__init__.py), the library exposes three key functions:

- **`plot()`** – Renders a single map to a given axis
- **`multiplot()`** – Orchestrates multiple maps on a shared figure
- **`Subplot`** – A lightweight data container for per-map configuration

The `multiplot()` implementation resides in [`prettymaps/draw.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py) (lines 1270–1320), where it coordinates figure creation, subplot iteration, and final rendering.

### How multiplot() Processes Multiple Maps

The function executes a four-stage pipeline, as implemented in the source:

1. **Figure initialization** – Creates a Matplotlib figure via `plt.figure()` and a single master axis with `plt.subplot(111)`

2. **Backend selection** – Checks for `plotter=True` in `kwargs` to toggle between standard Matplotlib rendering and the experimental Plotter API

3. **Subplot loop** – Iterates over each `Subplot` instance, calling the internal `plot()` function with merged parameters:

```python
plot(
    subplot.query,
    ax=ax,
    multiplot=True,
    **override_params(...),
    show=False,
)

```

This loop appears at [`draw.py`](https://github.com/marceloprates/prettymaps/blob/main/draw.py) lines 1280–1305. The `multiplot=True` flag suppresses duplicate attribution handling, while `override_params()` resolves conflicts between global and per-subplot settings.

4. **Finalization** – Hides axis borders with `ax.axis("off")` and optionally displays the figure

## Creating Subplot Containers

### The Subplot Data Class

Defined at [`draw.py`](https://github.com/marceloprates/prettymaps/blob/main/draw.py) lines 70–84, `Subplot` is a minimal container storing:

| Attribute | Purpose |
|-----------|---------|
| `query` | Geographic region string or OSM tag query |
| `kwargs` | Dictionary of overrides for that specific map |

Instantiation requires no dependencies beyond the class itself:

```python
from prettymaps import Subplot, multiplot

s1 = Subplot(query="New York, USA", kwargs={"load_preset": "default"})
s2 = Subplot(query="Paris, France", kwargs={"load_preset": "minimal"})

multiplot(s1, s2, figsize=(12, 8))

```

### Parameter Override Logic

The `override_params()` function (invoked within `multiplot`) implements careful precedence:

- Per-subplot `kwargs` take priority over global `multiplot()` arguments
- The `load_preset` flag receives special protection to prevent accidental override
- Style dictionaries, layer configurations, and drawing parameters all merge cleanly

This design allows each map to maintain distinct visual characteristics while sharing the same figure context.

## Practical Code Examples

### Two-City Comparison

Create a minimalist side-by-side of major cities:

```python
from prettymaps import Subplot, multiplot

ny = Subplot("New York, USA", kwargs={"load_preset": "default"})
tokyo = Subplot("Tokyo, Japan", kwargs={"load_preset": "minimal"})

multiplot(ny, tokyo, figsize=(12, 6))

```

### Custom Styles Per Subplot

Apply individual color schemes and layer configurations:

```python
from prettymaps import Subplot, multiplot

s1 = Subplot(
    query="Berlin, Germany",
    kwargs={
        "load_preset": "default",
        "style": {"land": "#e0e0e0", "background": "#ffffff"},
        "layers": {"buildings": {"fill": "#ffcc00", "alpha": 0.8}},
    },
)

s2 = Subplot(
    query="Copenhagen, Denmark",
    kwargs={
        "load_preset": "minimal",
        "style": {"land": "#f5f5f5"},
        "layers": {"water": {"fill": "#4a90d9", "alpha": 0.6}},
    },
)

multiplot(s1, s2, figsize=(14, 7), credit={"text": "European capitals comparison"})

```

### Three-Map Layout with Varied Complexity

Mix detailed and minimal renderings:

```python
from prettymaps import Subplot, multiplot

s1 = Subplot(
    "Sydney, Australia",
    kwargs={
        "load_preset": "default",
        "style": {"land": "#e8f5e9"},
        "layers": {
            "water": {"fill": "#b3e5fc"},
            "buildings": {"fill": "#a1887f"}
        },
    },
)

s2 = Subplot(
    "Rio de Janeiro, Brazil",
    kwargs={
        "load_preset": "default",
        "style": {"land": "#fff3e0"},
        "layers": {"vegetation": {"fill": "#c8e6c9"}},
    },
)

s3 = Subplot(
    "Reykjavik, Iceland",
    kwargs={"load_preset": "minimal", "style": {"land": "#eceff1"}},
)

multiplot(s1, s2, s3, figsize=(15, 5), credit={"text": "Global coastal cities"})

```

### Using the Plotter Backend

Enable interactive rendering for web-based workflows:

```python
from prettymaps import Subplot, multiplot

s1 = Subplot("Amsterdam, Netherlands", kwargs={"load_preset": "default"})
s2 = Subplot("Venice, Italy", kwargs={"load_preset": "default"})

multiplot(s1, s2, figsize=(10, 5), plotter=True)

```

## Key Source Files and Their Roles

| File | Function | Relevant Lines |
|------|----------|--------------|
| [`prettymaps/draw.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/draw.py) | Core implementation of `multiplot()`, `Subplot` class, and parameter merging | 70–84 (Subplot), 1280–1305 (multiplot loop) |
| [`prettymaps/__init__.py`](https://github.com/marceloprates/prettymaps/blob/main/prettymaps/__init__.py) | Public API exports | Full module |
| `prettymaps/presets/*.json` | Styling presets referenced via `load_preset` | Preset directory |
| [`tests/test.py`](https://github.com/marceloprates/prettymaps/blob/main/tests/test.py) | Validation suite including multiplot smoke tests | Test implementations |

## Configuration Options Reference

### Global multiplot() Parameters

| Parameter | Type | Effect |
|-----------|------|--------|
| `figsize` | tuple (width, height) | Dimensions in inches for the Matplotlib figure |
| `credit` | dict or None | Attribution text configuration; applied once to entire canvas |
| `plotter` | bool | Switches to experimental Plotter API when `True` |

### Per-Subplot Valid kwargs

Any argument accepted by `plot()` can be passed through `Subplot.kwargs`:

- `load_preset` – Name of JSON preset file
- `style` – Dictionary of color overrides
- `layers` – Layer-specific rendering rules
- `dpi` – Resolution for raster output
- `buffer` – Geographic expansion around query region

## Why the Design Works

**Stateless core rendering** – The `plot()` function accepts an external `ax` parameter and does not maintain global state, enabling safe repeated invocation.

**Controlled attribution** – The `multiplot=True` internal flag prevents duplicate copyright notices that would otherwise appear on every sub-render.

**Flexible parameter inheritance** – The `override_params()` merge strategy preserves intentional per-subplot customization without exposing complexity to users.

## Summary

- Import `Subplot` and `multiplot` from `prettymaps` to compose multiple maps
- Each `Subplot` requires a geographic `query` and accepts custom `kwargs` for styling
- `multiplot()` creates a shared Matplotlib figure, iterates through subplots, and applies parameter overrides automatically
- Use `load_preset`, `style`, and `layers` keys to differentiate individual maps
- Pass `plotter=True` for interactive Plotter-backend rendering
- Control global layout with `figsize` and unified attribution via `credit`

## Frequently Asked Questions

### What's the difference between `plot()` and `multiplot()`?

`plot()` renders a single map to a specified axis and handles its own figure management. `multiplot()` creates a figure, accepts multiple `Subplot` objects, and orchestrates their rendering with proper attribution handling and parameter merging. Use `plot()` for standalone maps; use `multiplot()` for composites.

### Can I mix different presets in one multiplot?

Yes. Each `Subplot` carries its own `kwargs` dictionary, including independent `load_preset` values. The `override_params()` function in [`draw.py`](https://github.com/marceloprates/prettymaps/blob/main/draw.py) protects preset loading during parameter merging, ensuring your per-subplot choices persist.

### How do I control the layout arrangement of multiple maps?

`multiplot()` currently uses a single axis (`plt.subplot(111)`) and overlays maps at different positions. For custom grid arrangements, call `plot()` directly with manually created axes using `plt.subplots()` or `GridSpec`, then omit `multiplot()` entirely. The `multiplot()` function prioritizes convenience over granular layout control.

### Why might attribution text appear duplicated, and how do I prevent it?

The `multiplot=True` internal flag suppresses per-subplot credit rendering. This flag is set automatically when `multiplot()` calls `plot()`. If using `plot()` directly for manual composition, pass `credit=None` to all but the final subplot to avoid duplication.