Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Drought duration

This how-to guide demonstrates how to download and process drought duration for a specific administratice (NUTS2) region. In this how-to, we retrieve both historical reanalysis and climate projection data for the region EL64 (Central Greece) and save it in a csv file.

Dataset: European Climate Data Explorer - Climate Indicators

Settings

User settings

admin_id = "EL64"

Setup of environment

import os
import zipfile
import cdsapi
import glob
from pathlib import Path
import xarray as xr
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import geopandas as gpd
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from functools import partial
from tqdm.auto import tqdm
# Define data directories
data_dir = Path("../data")
ecde_dir = data_dir / "ecde"
reanalysis_dir = ecde_dir / "reanalysis"
proj_dir = ecde_dir / "projections"
output_dir = data_dir / "EL64" / "drought_hazard"

# Create directories if they don't exist
for directory in [ecde_dir, reanalysis_dir, proj_dir, output_dir]:
    directory.mkdir(parents=True, exist_ok=True)

print(f"Data will be saved to: {ecde_dir}")
print(f"Output files will be saved to: {output_dir}")
Data will be saved to: ../data/ecde
Output files will be saved to: ../data/EL64/drought_hazard

Setup region specifics

regions_dir = data_dir / 'regions'
nuts_shp = regions_dir / 'NUTS_RG_20M_2024_4326' / 'NUTS_RG_20M_2024_4326.shp'
nuts_gdf = gpd.read_file(nuts_shp)

# Select the region of interest
sel_gdf = nuts_gdf[nuts_gdf['NUTS_ID'] == admin_id]
print(f"Region: {sel_gdf['NUTS_NAME'].values[0]}")
print(f"NUTS ID: {admin_id}")
print(f"Country: {sel_gdf['CNTR_CODE'].values[0]}")
print(f"Bounding box: {sel_gdf.geometry.total_bounds}")
Region: Στερεά Ελλάδα
NUTS ID: EL64
Country: EL
Bounding box: [21.39637798 37.98898161 24.67199242 39.27219519]

Download Hazard Data

Helper function to unzip downloaded data

The CDS API downloads data as zip files. We need a function to extract and rename the NetCDF files.

def unzip_ecde_data(zipfile_path):
    """
    Unzip ECDE data downloaded from CDS and rename to .nc extension.
    
    Parameters:
    -----------
    zipfile_path : Path or str
        Path to the zip file to extract
    """
    zipfile_path = Path(zipfile_path)
    
    with zipfile.ZipFile(zipfile_path, 'r') as zip_ref:
        names = zip_ref.namelist()
        zip_ref.extractall(zipfile_path.parent)
        
        for name in names:
            if name.split(".")[-1] == "nc":
                # Rename the extracted file to match the zip filename
                nc_path = zipfile_path.with_suffix('.nc')
                os.rename(zipfile_path.parent / name, nc_path)
                print(f"  Extracted: {nc_path.name}")
            else:
                # Remove non-NetCDF files
                os.remove(zipfile_path.parent / name)
    
    # Remove the zip file after extraction
    os.remove(zipfile_path)
    print(f"  Removed: {zipfile_path.name}")

Download reanalysis drought duration data

We’ll download reanalysis drought duration data from the ECDE dataset (1940-2023).

# Define filename and years for reanalysis data
reanalysis_zipfile = reanalysis_dir / "drought_duration_nuts2_reanalysis_1940_2023.zip"
reanalysis_ncfile = reanalysis_zipfile.with_suffix('.nc')

# Download reanalysis data
print("Downloading reanalysis drought duration data (1940-2023)...")
print("=" * 60)

# Skip if already downloaded
if reanalysis_ncfile.exists():
    print(f"Reanalysis data already exists, skipping download")
else:
    print(f"Downloading reanalysis data (1940-2023)...")
    
    dataset = "sis-ecde-climate-indicators"
    request = {
        "variable": ["duration_of_meteorological_droughts"],
        "origin": "reanalysis",
        "temporal_aggregation": ["yearly"],
        "spatial_aggregation": "regional_layer",
        "regional_layer": ["nuts_level_2"],
    }
    
    try:
        client = cdsapi.Client()
        client.retrieve(dataset, request).download(str(reanalysis_zipfile))
        unzip_ecde_data(reanalysis_zipfile)
        print(f"  ✓ Download complete")
    except Exception as e:
        print(f"  ✗ Error downloading reanalysis data: {e}")

print("=" * 60)
print(f"Reanalysis data download complete!")
Downloading reanalysis drought duration data (1940-2023)...
============================================================
Downloading reanalysis data (1940-2023)...
2026-02-05 16:38:57,644 INFO Request ID is 343e3d63-82e5-4819-b3a3-84616148ad65
2026-02-05 16:38:57,669 INFO status has been updated to accepted
2026-02-05 16:39:11,036 INFO status has been updated to running
2026-02-05 16:39:18,731 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_reanalysis_1940_2023.nc
  Removed: drought_duration_nuts2_reanalysis_1940_2023.zip
  ✓ Download complete
============================================================
Reanalysis data download complete!

Download drought projections

We’ll download climate projection data (1950-2100) for multiple Global Climate Models (GCMs), Regional Climate Models (RCMs), scenarios (RCPs), and ensemble members.

We’ll download a subset of available model combinations. You can adjust these lists based on your needs.

# Define model combinations
# Note: Not all combinations are available in the dataset

gcms = ["ec_earth", "hadgem2_es", "ipsl_cm5a_mr", "mpi_esm_lr", "noresm1_m"]
rcms = ["cclm4_8_17", "hirham5", "racmo22e", "rca4", "wrf381p"]
rcps = ["rcp4_5", "rcp8_5"]
enss = ["r12i1p1", "r1i1p1", "r3i1p1"]

print(f"Model combinations to attempt:")
print(f"  GCMs: {len(gcms)}")
print(f"  RCMs: {len(rcms)}")
print(f"  RCPs: {len(rcps)}")
print(f"  Ensemble members: {len(enss)}")
print(f"  Maximum possible downloads: {len(gcms) * len(rcms) * len(rcps) * len(enss)}")
print(f"\nNote: Not all combinations are available in the dataset; we will check for their availability.")
Model combinations to attempt:
  GCMs: 5
  RCMs: 5
  RCPs: 2
  Ensemble members: 3
  Maximum possible downloads: 150

Note: Not all combinations are available in the dataset; we will check for their availability.
# Download projection data
print("Downloading drought projection data (1950-2100)...")
print("=" * 60)

proj_files = []
download_count = 0
skip_count = 0
error_count = 0

# Calculate total iterations for progress bar
total_iterations = len(gcms) * len(rcms) * len(rcps) * len(enss)

# Create progress bar
with tqdm(total=total_iterations, desc="Processing model combinations") as pbar:
    for gcm in gcms:
        for rcm in rcms:
            for rcp in rcps:
                for ens in enss:
                    
                    years = [str(y) for y in range(1950, 2101)]
                    
                    # Create filename
                    proj_zipfile = proj_dir / f"drought_duration_nuts2_{gcm}_{rcm}_{rcp}_{ens}_1950_2100.zip"
                    proj_ncfile = proj_zipfile.with_suffix('.nc')
                    
                    # Skip if already downloaded
                    if proj_ncfile.exists():
                        skip_count += 1
                        proj_files.append(proj_ncfile)
                        pbar.update(1)
                        continue
                    
                    model_info = f"{gcm}/{rcm}/{rcp}/{ens}"
                    pbar.set_postfix_str(f"Downloading: {model_info}")
                    
                    dataset = "sis-ecde-climate-indicators"
                    request = {
                        "variable": ["duration_of_meteorological_droughts"],
                        "origin": "projections",
                        "gcm": gcm,
                        "rcm": rcm,
                        "experiment": rcp,
                        "ensemble_member": ens,
                        "temporal_aggregation": ["yearly"],
                        "spatial_aggregation": "regional_layer",
                        "regional_layer": ["nuts_level_2"],
                    }
                    
                    try:
                        client = cdsapi.Client()
                        client.retrieve(dataset, request).download(str(proj_zipfile))
                        unzip_ecde_data(proj_zipfile)
                        proj_files.append(proj_ncfile)
                        download_count += 1
                    except Exception as e:
                        error_count += 1
                        # Silently count errors without printing each one
                    
                    pbar.update(1)

print("=" * 60)
print(f"Projection data download summary:")
print(f"  New downloads: {download_count}")
print(f"  Already existed: {skip_count}")
print(f"  Errors/unavailable: {error_count}")
print(f"  Total projection files: {len(proj_files)}")
Downloading drought projection data (1950-2100)...
============================================================
Loading...
2026-02-05 16:41:37,080 INFO Request ID is 0bacf384-f5b1-4835-9d6c-d727e7b42767
2026-02-05 16:41:37,100 INFO status has been updated to accepted
2026-02-05 16:41:50,616 INFO status has been updated to running
2026-02-05 16:41:58,231 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_ec_earth_hirham5_rcp4_5_r3i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_ec_earth_hirham5_rcp4_5_r3i1p1_1950_2100.zip
2026-02-05 16:41:58,821 INFO Request ID is 39d36ce3-b7e9-488a-972d-bf8d1870f99b
2026-02-05 16:41:58,840 INFO status has been updated to accepted
2026-02-05 16:42:12,539 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_ec_earth_hirham5_rcp8_5_r3i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_ec_earth_hirham5_rcp8_5_r3i1p1_1950_2100.zip
2026-02-05 16:42:12,866 INFO Request ID is 5a3279b8-c41e-41f9-9c83-b1fa0153da73
2026-02-05 16:42:12,878 INFO status has been updated to accepted
2026-02-05 16:42:26,240 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_ec_earth_racmo22e_rcp4_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_ec_earth_racmo22e_rcp4_5_r1i1p1_1950_2100.zip
2026-02-05 16:42:26,656 INFO Request ID is 2567ac8a-a726-4fb0-bf26-0d05fa840171
2026-02-05 16:42:26,668 INFO status has been updated to accepted
2026-02-05 16:42:40,153 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_ec_earth_racmo22e_rcp8_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_ec_earth_racmo22e_rcp8_5_r1i1p1_1950_2100.zip
2026-02-05 16:42:41,191 INFO Request ID is 69f405cd-531c-44ce-a9ef-fa1129c2e615
2026-02-05 16:42:41,225 INFO status has been updated to accepted
2026-02-05 16:43:02,183 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_ec_earth_rca4_rcp4_5_r12i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_ec_earth_rca4_rcp4_5_r12i1p1_1950_2100.zip
2026-02-05 16:43:02,970 INFO Request ID is 2f330d32-0d8e-4f58-bbf8-c8c2ff063ad2
2026-02-05 16:43:03,007 INFO status has been updated to accepted
2026-02-05 16:43:11,364 INFO status has been updated to running
2026-02-05 16:43:16,453 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_ec_earth_rca4_rcp8_5_r12i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_ec_earth_rca4_rcp8_5_r12i1p1_1950_2100.zip
2026-02-05 16:43:18,198 INFO Request ID is 9bee1870-610a-41f3-88c6-e9bce94f2153
2026-02-05 16:43:18,328 INFO status has been updated to accepted
2026-02-05 16:43:32,150 INFO status has been updated to running
2026-02-05 16:43:39,792 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_hadgem2_es_racmo22e_rcp4_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_hadgem2_es_racmo22e_rcp4_5_r1i1p1_1950_2100.zip
2026-02-05 16:43:40,515 INFO Request ID is b6b48e4b-30fa-4f24-8ab6-f92b50c6d7ce
2026-02-05 16:43:40,540 INFO status has been updated to accepted
2026-02-05 16:43:54,286 INFO status has been updated to running
2026-02-05 16:44:02,763 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_hadgem2_es_racmo22e_rcp8_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_hadgem2_es_racmo22e_rcp8_5_r1i1p1_1950_2100.zip
2026-02-05 16:44:03,686 INFO Request ID is b74b5bf2-e9fd-41df-a4a0-8fd83f5b3490
2026-02-05 16:44:03,741 INFO status has been updated to accepted
2026-02-05 16:44:17,038 INFO status has been updated to running
2026-02-05 16:44:24,691 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_hadgem2_es_rca4_rcp4_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_hadgem2_es_rca4_rcp4_5_r1i1p1_1950_2100.zip
2026-02-05 16:44:25,129 INFO Request ID is 916f92d1-2374-45e6-b98d-cfd4209252bd
2026-02-05 16:44:25,141 INFO status has been updated to accepted
2026-02-05 16:44:38,647 INFO status has been updated to running
2026-02-05 16:44:46,260 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_hadgem2_es_rca4_rcp8_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_hadgem2_es_rca4_rcp8_5_r1i1p1_1950_2100.zip
2026-02-05 16:44:49,316 INFO Request ID is beacf924-468a-49cb-94a2-cbc76b854a3c
2026-02-05 16:44:49,330 INFO status has been updated to accepted
2026-02-05 16:45:02,610 INFO status has been updated to running
2026-02-05 16:45:10,362 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_ipsl_cm5a_mr_wrf381p_rcp4_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_ipsl_cm5a_mr_wrf381p_rcp4_5_r1i1p1_1950_2100.zip
2026-02-05 16:45:10,872 INFO Request ID is 6e35fe0c-8793-4e11-8943-acf1431e56c4
2026-02-05 16:45:11,201 INFO status has been updated to accepted
2026-02-05 16:45:24,511 INFO status has been updated to running
2026-02-05 16:45:32,126 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_ipsl_cm5a_mr_wrf381p_rcp8_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_ipsl_cm5a_mr_wrf381p_rcp8_5_r1i1p1_1950_2100.zip
2026-02-05 16:45:32,544 INFO Request ID is 44945470-090e-43ff-af85-1b794466fa14
2026-02-05 16:45:32,562 INFO status has been updated to accepted
2026-02-05 16:45:53,478 INFO status has been updated to running
2026-02-05 16:46:04,886 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_mpi_esm_lr_cclm4_8_17_rcp4_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_mpi_esm_lr_cclm4_8_17_rcp4_5_r1i1p1_1950_2100.zip
2026-02-05 16:46:05,622 INFO Request ID is cf1b8069-5e52-4828-99db-2d47281a1970
2026-02-05 16:46:05,641 INFO status has been updated to accepted
2026-02-05 16:46:19,296 INFO status has been updated to running
2026-02-05 16:46:26,905 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_mpi_esm_lr_cclm4_8_17_rcp8_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_mpi_esm_lr_cclm4_8_17_rcp8_5_r1i1p1_1950_2100.zip
2026-02-05 16:46:28,572 INFO Request ID is b2430efb-bb0c-40c4-bfbb-a3d516fe76b8
2026-02-05 16:46:28,613 INFO status has been updated to accepted
2026-02-05 16:46:41,897 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_mpi_esm_lr_rca4_rcp4_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_mpi_esm_lr_rca4_rcp4_5_r1i1p1_1950_2100.zip
2026-02-05 16:46:42,319 INFO Request ID is e2f4e868-a0bf-49d7-a2a6-5ee8754a3915
2026-02-05 16:46:42,348 INFO status has been updated to accepted
2026-02-05 16:46:55,779 INFO status has been updated to running
2026-02-05 16:47:03,410 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_mpi_esm_lr_rca4_rcp8_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_mpi_esm_lr_rca4_rcp8_5_r1i1p1_1950_2100.zip
2026-02-05 16:47:05,175 INFO Request ID is afd7a8fa-edc6-45d6-9fcd-6a8dd23895b8
2026-02-05 16:47:05,198 INFO status has been updated to accepted
2026-02-05 16:47:18,512 INFO status has been updated to running
2026-02-05 16:47:37,526 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_noresm1_m_hirham5_rcp4_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_noresm1_m_hirham5_rcp4_5_r1i1p1_1950_2100.zip
2026-02-05 16:47:39,265 INFO Request ID is 1cff660a-a661-48f2-9f17-f32453bfbccd
2026-02-05 16:47:40,826 INFO status has been updated to accepted
2026-02-05 16:48:13,379 INFO status has been updated to running
2026-02-05 16:48:30,485 INFO status has been updated to successful
Loading...
  Extracted: drought_duration_nuts2_noresm1_m_hirham5_rcp8_5_r1i1p1_1950_2100.nc
  Removed: drought_duration_nuts2_noresm1_m_hirham5_rcp8_5_r1i1p1_1950_2100.zip
============================================================
Projection data download summary:
  New downloads: 18
  Already existed: 0
  Errors/unavailable: 132
  Total projection files: 18

Process Hazard Data

Process reanalysis data

Now we’ll read the reanalysis drought duration data and extract information for our region (EL64).

# Read reanalysis NetCDF file
reanalysis_ncfile = reanalysis_dir / "drought_duration_nuts2_reanalysis_1940_2023.nc"

if reanalysis_ncfile.exists():
    # Open reanalysis data
    drought_dur_reanalysis = xr.open_dataset(reanalysis_ncfile)
    print("\nReanalysis dataset:")
    print(drought_dur_reanalysis)
    
    # Extract data for EL64
    drought_dur_reanalysis_el64 = drought_dur_reanalysis.sel(nuts=admin_id)
    print(f"\nData for {admin_id}:")
    print(drought_dur_reanalysis_el64)
else:
    print("Reanalysis data file not found. Please download the data first.")
/usr/local/apps/python3/3.12.11-01/lib/python3.12/site-packages/gribapi/__init__.py:23: UserWarning: ecCodes 2.42.0 or higher is recommended. You are running version 2.31.0
  warnings.warn(

Reanalysis dataset:
<xarray.Dataset> Size: 230kB
Dimensions:      (nuts: 334, time: 84)
Coordinates:
  * nuts         (nuts) <U4 5kB 'DE50' 'DE60' 'DE71' ... 'NO06' 'NO07' 'NO08'
  * time         (time) datetime64[ns] 672B 1940-01-01 1941-01-01 ... 2023-01-01
    realization  int64 8B ...
Data variables:
    dmd          (nuts, time) float64 224kB ...

Data for EL64:
<xarray.Dataset> Size: 1kB
Dimensions:      (time: 84)
Coordinates:
  * time         (time) datetime64[ns] 672B 1940-01-01 1941-01-01 ... 2023-01-01
    realization  int64 8B ...
    nuts         <U4 16B 'EL64'
Data variables:
    dmd          (time) float64 672B ...

Process projection data

We’ll read all projection files and organize them by model combination.

# Find all projection NetCDF files
proj_nc_files = sorted(proj_dir.glob("drought_duration_nuts2_*_1950_2100.nc"))
print(f"Found {len(proj_nc_files)} projection data files")

print(f"\nAvailable model combinations:")
for i, file in enumerate(proj_nc_files[:5]):
    print(f"  {i+1}. {file.stem}")
if len(proj_nc_files) > 5:
    print(f"  ... and {len(proj_nc_files) - 5} more")
Found 18 projection data files

Available model combinations:
  1. drought_duration_nuts2_ec_earth_hirham5_rcp4_5_r3i1p1_1950_2100
  2. drought_duration_nuts2_ec_earth_hirham5_rcp8_5_r3i1p1_1950_2100
  3. drought_duration_nuts2_ec_earth_racmo22e_rcp4_5_r1i1p1_1950_2100
  4. drought_duration_nuts2_ec_earth_racmo22e_rcp8_5_r1i1p1_1950_2100
  5. drought_duration_nuts2_ec_earth_rca4_rcp4_5_r12i1p1_1950_2100
  ... and 13 more
# Load projection data for each model file
projection_data = {}

for file in proj_nc_files:
    # Extract model info from filename
    # Format: drought_duration_nuts2_{gcm}_{rcm}_{rcp}_{ens}_1950_2100.nc
    parts = file.stem.split('_')
    
    # Find where RCP starts (it always starts with 'rcp')
    rcp_idx = next((i for i, p in enumerate(parts) if p.startswith('rcp')), None)
    
    if rcp_idx:
        gcm = '_'.join(parts[3:rcp_idx-1])  # Everything between 'nuts2' and RCM
        rcm = parts[rcp_idx-1]  # Part just before RCP
        rcp = f"{parts[rcp_idx]}_{parts[rcp_idx+1]}"  # e.g., rcp4_5 or rcp8_5
        ens = parts[rcp_idx+2]  # Ensemble member after RCP (before year range)
        
        model_key = f"{gcm}_{rcm}_{rcp}_{ens}"
        
        try:
            # Load dataset and extract EL64 data
            ds = xr.open_dataset(file)
            ds_el64 = ds.sel(nuts=admin_id)
            projection_data[model_key] = ds_el64
        except Exception as e:
            print(f"Error loading {model_key}: {e}")

print(f"\nSuccessfully loaded {len(projection_data)} model combinations")

# Show example
if len(projection_data) > 0:
    example_key = list(projection_data.keys())[0]
    print(f"\nExample dataset ({example_key}):")
    print(projection_data[example_key])

Successfully loaded 18 model combinations

Example dataset (ec_earth_hirham5_rcp4_5_r3i1p1):
<xarray.Dataset> Size: 2kB
Dimensions:  (time: 150)
Coordinates:
  * time     (time) datetime64[ns] 1kB 1951-01-01 1952-01-01 ... 2100-01-01
    nuts     <U4 16B 'EL64'
Data variables:
    dmd      (time) float64 1kB ...

Save Regional Hazard Data

Finally, we’ll save all the timeseries data to CSV files for further analysis.

# Save reanalysis data to CSV
if 'drought_dur_reanalysis_el64' in locals():
    reanalysis_df = drought_dur_reanalysis_el64['dmd'].to_dataframe().reset_index()
    reanalysis_df['scenario'] = 'reanalysis'
    reanalysis_df['model'] = 'reanalysis'
    reanalysis_csv = output_dir / f"drought_duration_reanalysis_{admin_id}.csv"
    reanalysis_df.to_csv(reanalysis_csv, index=False)
    print(f"Saved reanalysis data to: {reanalysis_csv}")
    print(f"  Shape: {reanalysis_df.shape}")
    print(f"  Columns: {list(reanalysis_df.columns)}")
Saved reanalysis data to: data/EL64/drought_hazard/drought_duration_reanalysis_EL64.csv
  Shape: (84, 6)
  Columns: ['time', 'realization', 'nuts', 'dmd', 'scenario', 'model']
# Save projection data to CSV
if len(projection_data) > 0:
    all_proj_data = []
    
    for model_key, ds in projection_data.items():
        # Parse model information from model_key
        # Format: {gcm}_{rcm}_{rcp}_{ens}
        parts = model_key.split('_')
        
        # Find where RCP starts (it always has format rcp4 or rcp8)
        rcp_idx = next(i for i, p in enumerate(parts) if p.startswith('rcp'))
        
        gcm = '_'.join(parts[:rcp_idx-1])  # Everything before RCM
        rcm = parts[rcp_idx-1]  # Part just before RCP
        rcp = f"{parts[rcp_idx]}_{parts[rcp_idx+1]}"  # e.g., rcp4_5 or rcp8_5
        ens = '_'.join(parts[rcp_idx+2:])  # Everything after RCP (e.g., r1i1p1)
        
        # Convert to dataframe
        df = ds['dmd'].to_dataframe().reset_index()
        df['scenario'] = rcp.upper()  # Use RCP4_5 or RCP8_5
        df['gcm'] = gcm
        df['rcm'] = rcm
        df['ensemble'] = ens
        df['model'] = model_key
        
        all_proj_data.append(df)
    
    # Combine all projection data
    proj_df = pd.concat(all_proj_data, ignore_index=True)
    
    # Save to CSV
    proj_csv = output_dir / f"drought_duration_projections_{admin_id}.csv"
    proj_df.to_csv(proj_csv, index=False)
    print(f"\nSaved projection data to: {proj_csv}")
    print(f"  Shape: {proj_df.shape}")
    print(f"  Columns: {list(proj_df.columns)}")
    print(f"  Unique models: {proj_df['model'].nunique()}")
    print(f"  Scenarios: {proj_df['scenario'].unique()}")

Saved projection data to: data/EL64/drought_hazard/drought_duration_projections_EL64.csv
  Shape: (10340, 8)
  Columns: ['time', 'nuts', 'dmd', 'scenario', 'gcm', 'rcm', 'ensemble', 'model']
  Unique models: 18
  Scenarios: ['RCP4_5' 'RCP8_5']
# Create a combined CSV with both reanalysis and projections
if 'reanalysis_df' in locals() and 'proj_df' in locals():
    # Align columns
    common_cols = ['time', 'nuts', 'dmd', 'scenario', 'model']
    
    reanalysis_df_clean = reanalysis_df[common_cols].copy()
    proj_df_clean = proj_df[['time', 'nuts', 'dmd', 'scenario', 'model']].copy()
    
    combined_df = pd.concat([reanalysis_df_clean, proj_df_clean], ignore_index=True)
    combined_df = combined_df.sort_values('time').reset_index(drop=True)
    
    combined_csv = output_dir / f"drought_duration_all_{admin_id}.csv"
    combined_df.to_csv(combined_csv, index=False)
    print(f"\nSaved combined data to: {combined_csv}")
    print(f"  Shape: {combined_df.shape}")
    print(f"  Time range: {combined_df['time'].min()} to {combined_df['time'].max()}")

Output summary

Output files created:

  • drought_duration_reanalysis_{admin_id}.csv - Reanalysis drought duration (1940-2023)

  • drought_duration_projections_{admin_id}.csv - All projections of drought duration (1950-2100)

  • drought_duration_all_{admin_id}.csv - Combined reanalysis and projections

These CSV files can now be used for further analysis, risk assessment, or integration with exposure and vulnerability data.