Why Is My GeoPandas Plot Blank or Empty? How to Fix It

Problem statement

You call .plot() on a GeoDataFrame and nothing useful appears. The figure opens but the axes are empty, the saved image is white, or in a script no window shows at all.

What users usually mean is one of these symptoms:

  • a blank white figure with empty axes and no geometry
  • a window that opens and closes immediately in a script
  • a saved PNG that is completely white
  • axes that render but no shapes are drawn
  • a choropleth where every feature is the same flat color

In most cases, the real cause is one of these data or display issues:

  • the GeoDataFrame is empty or every geometry is null
  • the figure was never displayed because plt.show() is missing
  • a filter removed every feature before plotting
  • the column used for coloring is all NaN
  • you plotted before actually reading the data
  • the extent is zero-area, so everything draws on a single point
  • an existing ax was reused and the data went to a different axes

The practical fix is to confirm the data has visible geometry, then confirm the figure is actually being shown.

Quick answer

If your GeoPandas plot is blank or empty:

  1. Print len(gdf) and gdf.geometry.isna().sum() to confirm there is geometry to draw.
  2. Check gdf.geometry.is_empty.sum() for empty geometries.
  3. Make sure you call plt.show() in a script, or use an inline backend in Jupyter.
  4. If coloring by a column, check that column for NaN with gdf["value"].isna().sum().
  5. Print gdf.total_bounds to confirm the extent is not zero-area.
  6. Plot onto an explicit ax from plt.subplots() so the data lands where you expect.
import geopandas as gpd
import matplotlib.pyplot as plt

gdf = gpd.read_file("data/regions.gpkg")

print("Rows:", len(gdf))
print("Null geometries:", gdf.geometry.isna().sum())
print("Empty geometries:", gdf.geometry.is_empty.sum())
print("Bounds:", gdf.total_bounds)

fig, ax = plt.subplots(figsize=(8, 6))
gdf.plot(ax=ax, edgecolor="black")
plt.show()

Data or display?

Flowchart — Is a blank plot a data problem or a display problem?
Is a blank plot a data problem or a display problem?

Step-by-step solution

Step 1: Check that the GeoDataFrame is not empty

A blank plot is often a blank dataset. If the read or a filter returned nothing, there is nothing to draw.

import geopandas as gpd

gdf = gpd.read_file("data/regions.gpkg")

print("Rows:", len(gdf))
print(gdf.head())

If len(gdf) is 0, the problem is upstream of plotting. Check the file path, the layer name, and any filter you applied before .plot().

Step 2: Check for null and empty geometries

A GeoDataFrame can have rows but still draw nothing if the geometry column is all null or all empty.

import geopandas as gpd

gdf = gpd.read_file("data/regions.gpkg")

print("Null geometries:", gdf.geometry.isna().sum())
print("Empty geometries:", gdf.geometry.is_empty.sum())

Keep only rows that have real geometry before plotting:

gdf = gdf[gdf.geometry.notna() & ~gdf.geometry.is_empty]
print("Drawable rows:", len(gdf))

If nothing remains after this filter, the source data has no usable geometry.

Step 3: Make sure the figure is actually displayed

In a plain Python script, building a plot does not show it. Without plt.show(), the script can finish and the window never appears.

import geopandas as gpd
import matplotlib.pyplot as plt

gdf = gpd.read_file("data/regions.gpkg")

gdf.plot(edgecolor="black")
plt.show()

In Jupyter, the figure usually renders automatically with the inline backend. If it does not, run %matplotlib inline once in a cell. If you are saving instead of showing, use plt.savefig("map.png") and open the file.

Step 4: Check the column used for coloring for NaN

When you plot a choropleth with column=, rows where that column is NaN are not colored. If every value is NaN, the map looks blank or flat.

import geopandas as gpd

gdf = gpd.read_file("data/regions.gpkg")

print("NaN values in column:", gdf["population"].isna().sum())
print(gdf["population"].describe())

If the column is all NaN, fix the data or choose a column that has values. You can also make missing values visible:

import matplotlib.pyplot as plt

ax = gdf.plot(
    column="population",
    legend=True,
    missing_kwds={"color": "lightgray", "label": "No data"},
)
plt.show()

Step 5: Check the CRS and extent

A zero-area or degenerate extent can make every feature collapse onto a single point, which looks like an empty map.

import geopandas as gpd

gdf = gpd.read_file("data/regions.gpkg")

print("CRS:", gdf.crs)
print("Bounds:", gdf.total_bounds)

gdf.total_bounds returns:

[minx, miny, maxx, maxy]

If minx == maxx and miny == maxy, the data covers no area, so it draws as a dot. That usually means only one identical point remains, or the geometry is degenerate. A missing CRS does not by itself blank the plot, but it is worth confirming while you inspect the data.

Step 6: Plot onto an explicit axes

If you reuse an ax from an earlier figure, your data can be drawn onto axes you are not looking at. Create a fresh figure and axes for each plot.

import geopandas as gpd
import matplotlib.pyplot as plt

gdf = gpd.read_file("data/regions.gpkg")

fig, ax = plt.subplots(figsize=(8, 6))
gdf.plot(ax=ax, edgecolor="black")
plt.show()

This makes it explicit which axes the geometry goes to, which removes a common source of "nothing shows up" confusion.

Code examples

Example 1: Full diagnostic before plotting

import geopandas as gpd
import matplotlib.pyplot as plt

gdf = gpd.read_file("data/regions.gpkg")

print("Rows:", len(gdf))
print("Null geometries:", gdf.geometry.isna().sum())
print("Empty geometries:", gdf.geometry.is_empty.sum())
print("CRS:", gdf.crs)
print("Bounds:", gdf.total_bounds)

fig, ax = plt.subplots(figsize=(8, 6))
gdf.plot(ax=ax, edgecolor="black")
plt.show()

This sequence usually tells you immediately whether the problem is the data or the display.

Example 2: Drop null and empty geometries, then plot

import geopandas as gpd
import matplotlib.pyplot as plt

gdf = gpd.read_file("data/regions.gpkg")

clean = gdf[gdf.geometry.notna() & ~gdf.geometry.is_empty]

print("Original rows:", len(gdf))
print("Drawable rows:", len(clean))

clean.plot(edgecolor="black", figsize=(8, 6))
plt.show()

If clean is empty, the source file has no usable geometry and plotting cannot help.

Example 3: Color by a column safely

import geopandas as gpd
import matplotlib.pyplot as plt

gdf = gpd.read_file("data/regions.gpkg")

print("NaN in column:", gdf["population"].isna().sum())

fig, ax = plt.subplots(figsize=(8, 6))
gdf.plot(
    column="population",
    legend=True,
    missing_kwds={"color": "lightgray", "label": "No data"},
    ax=ax,
)
plt.show()

Rows with NaN now draw in gray instead of disappearing, so the map is no longer blank.

Example 4: Save the figure instead of showing it

import geopandas as gpd
import matplotlib.pyplot as plt

gdf = gpd.read_file("data/regions.gpkg")

fig, ax = plt.subplots(figsize=(8, 6))
gdf.plot(ax=ax, edgecolor="black")

fig.savefig("output/map.png", dpi=150, bbox_inches="tight")
plt.close(fig)

Use this in headless scripts where no display is available. If the saved PNG is still white, the data was empty, not the display.

Explanation

A GeoPandas plot has two separate parts: the Matplotlib axes and the geometry drawn onto them. A blank figure means the axes were created but no geometry reached them, or the figure was never shown.

The most common causes are:

  • no drawable geometry
    An empty GeoDataFrame, all-null geometry, or all-empty geometry leaves the axes with nothing to draw.

  • the figure was never displayed
    In a script, .plot() builds the figure but plt.show() is what renders it. Without it, the work is silently discarded.

  • all values are NaN in the color column
    With column=, features that are NaN are not assigned a color, so a fully NaN column produces a blank or flat map.

  • degenerate extent
    If every coordinate is identical, the data has zero area and collapses to a single point.

  • wrong axes
    Passing a reused ax sends the geometry to a figure you are not viewing.

The key distinction is between an empty axes and empty data. An empty axes with valid data points to a display problem such as a missing plt.show() or the wrong backend. An empty axes with no valid geometry points to a data problem you must fix before plotting.

Edge cases or notes

Jupyter versus a script

In Jupyter, the inline backend renders the last expression of a cell automatically, so a missing plt.show() is rarely the issue. In a plain script you almost always need plt.show() to see a window.

Interactive backends

If plt.show() opens a window that closes instantly, you may have a non-interactive backend. Check it with matplotlib.get_backend(). On a headless server there is no display, so save the figure with savefig() instead of showing it.

Saving versus showing

plt.show() renders to a window and savefig() writes to a file. Calling plt.show() before savefig() can leave you with a blank file on some backends, because the figure may be cleared after display. Save first, then show, or use separate figures.

Plotting before reading the data

If you build the figure before the read completes or before assigning the result, you can plot an empty or stale object. Confirm gdf is populated immediately before .plot().

All geometries filtered out

A chained filter such as gdf[gdf["area"] > 1000] can quietly return zero rows. Print len() after each filter so you know when the data became empty.

A single point looks like nothing

One point on default axes can be invisible at the chosen scale. Increase markersize or set explicit axis limits so the feature is easy to see.

FAQ

Why is my GeoPandas plot blank?

Usually because there is no drawable geometry or the figure was never shown. Check len(gdf), gdf.geometry.isna().sum(), and gdf.geometry.is_empty.sum(), then make sure you call plt.show().

Why does nothing appear when I run .plot() in a script?

Building a plot does not display it. In a script you need plt.show() to open a window, or savefig() to write the figure to a file.

Why is my choropleth map all one color or blank?

The column you passed to column= may be all NaN, so no feature gets a color. Check the column with isna().sum() and use missing_kwds to make missing values visible.

Why is my saved map image completely white?

The figure had no geometry to draw, or it was cleared by plt.show() before savefig(). Confirm the GeoDataFrame is not empty and save the figure before showing it.

Why does my GeoPandas plot show axes with coordinate numbers but no shapes?

The axes rendered, so this is a data problem, not a display one: the geometry is null, empty, or filtered out. Run gdf.geometry.notna().sum() and (~gdf.geometry.is_empty).sum() to confirm there is something drawable before plotting.

Why do two layers plot in different places or one disappears off-screen?

The layers are almost certainly in different CRS, so their coordinate ranges do not overlap and one falls outside the visible extent. Reproject one to match the other with layer2 = layer2.to_crs(layer1.crs) before plotting them on the same ax.

Why is my plot blank only when I save with savefig but fine on screen?

You likely called plt.show() before fig.savefig(); some backends clear the figure after display, leaving a white file. Save first, then show, and pass the explicit figure with fig.savefig("map.png") rather than relying on the current figure.

How do I make a single point or tiny feature visible instead of an empty-looking plot?

A lone point can render too small to see at the default scale. Increase markersize and set explicit limits, for example gdf.plot(markersize=50) followed by ax.set_xlim(...), or buffer the point so it has visible area.