Skip to content

Instantly share code, notes, and snippets.

@bennyistanto
Last active May 25, 2025 07:46
Show Gist options
  • Save bennyistanto/98038d0a372874f380c4126f0c1b580a to your computer and use it in GitHub Desktop.
Save bennyistanto/98038d0a372874f380c4126f0c1b580a to your computer and use it in GitHub Desktop.
Landcover annual transitions in hectares by country

Landcover Zonal Statistics & Transition Analysis

This repository provides two complementary workflows for deriving landcover area summaries and full transition matrices from MODIS IGBP or ESA CCI landcover datasets. Both workflows produce per‑year class area CSVs and comprehensive inter‑annual transition tables, then optionally split those tables by ISO3 code.


🔧 Requirements

  • Python 3.8+
  • geopandas
  • rasterstats
  • pandas
  • numpy
  • rasterio
  • xarray (only for NetCDF inputs)
  • tqdm

Install via conda or pip:

conda install geopandas rasterio rasterstats xarray pandas numpy tqdm
# or
pip install geopandas rasterio rasterstats xarray pandas numpy tqdm

📝 Notebook 1: zonal_histogram_annualtransitions_landcover.ipynb

Purpose

  1. Compute per‑year class areas: For each annual raster (GeoTIFF/NetCDF), run a zonal histogram by your admin boundaries to count pixels per IGBP/LCCS class, convert counts to hectares, and write both per‑year and combined CSV outputs.
  2. Build full transition matrices: For every pair of consecutive years, encode each pixel’s class change as 100*source + target, perform zonal histograms on that code, and output a complete source→target matrix (including zeros) per year.

Key Steps

  1. Per‑pixel transition code:

    trans = arr_prev.astype(np.int32)*100 + arr_curr.astype(np.int32)

    Assigns each pixel a unique integer for its (source, target) classes.

  2. Zonal counting:

    stats = zonal_stats(
      zones, trans,
      affine=transform,
      categorical=True,
      all_touched=True,
      nodata=-999
    )

    Buckets pixels by transition code per zone, returning {code: count} dicts.

  3. Area conversion:

    hectares = count * pixel_area_ha

    Converts pixel counts into hectares (25 ha for MODIS; adjust for other resolutions).

  4. Memory management: Frequent gc.collect() calls free Python memory between years to avoid OOM.


📝 Notebook 2: landcover_transitions_iso3.ipynb

Purpose

Splits the master transition table by ISO3 code and aggregates multiple polygons:

sub = (
  df[df.iso_3 == iso]
    .groupby(['year','source','target'], as_index=False)['hectares']
    .sum()
    .rename(columns={'hectares':'value'})
)
sub.to_csv(f'transitions_{iso}.csv', index=False)

This ensures each country’s output contains one record per (year, source, target) with summed hectare values, even if that country has multiple boundary parts.

Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment