Skip to content

Commit df25d91

Browse files
milestone_2
1 parent ee11fca commit df25d91

11 files changed

Lines changed: 18331 additions & 0 deletions
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Create emdat_clean.csv from raw EM-DAT Excel file
4+
This script processes the raw data and creates the format expected by the website.
5+
"""
6+
7+
import pandas as pd
8+
from pathlib import Path
9+
10+
# Paths
11+
DATA_DIR = Path('docs/data')
12+
INPUT_FILE = DATA_DIR / 'public_emdat_incl_hist_2026-03-17.xlsx'
13+
OUTPUT_FILE = DATA_DIR / 'emdat_clean.csv'
14+
15+
# Configuration
16+
SHEET_NAME = 'EM-DAT Data'
17+
YEAR_START = 1975
18+
YEAR_END = 2025
19+
20+
print('Creating emdat_clean.csv for website...')
21+
print(f'Reading: {INPUT_FILE}')
22+
23+
# Load the Excel file
24+
df_full = pd.read_excel(INPUT_FILE, sheet_name=SHEET_NAME)
25+
print(f'Loaded {len(df_full):,} total records from Excel')
26+
27+
# Filter to analysis period and natural disasters only
28+
df = df_full[
29+
(df_full['Start Year'].between(YEAR_START, YEAR_END, inclusive='both')) &
30+
(df_full['Disaster Group'] == 'Natural')
31+
].copy()
32+
33+
print(f'Filtered to {YEAR_START}-{YEAR_END}, Natural disasters: {len(df):,} records')
34+
35+
# Select and rename columns for website
36+
df_clean = df[[
37+
'Start Year', 'ISO', 'Country', 'Region', 'Subregion',
38+
'Disaster Type', 'Disaster Subtype', 'Event Name',
39+
'Total Deaths', 'Total Affected',
40+
'Total Damage, Adjusted (\'000 US$)',
41+
'Latitude', 'Longitude'
42+
]].copy()
43+
44+
df_clean.columns = [
45+
'year', 'iso', 'country', 'region', 'subregion',
46+
'type', 'type_detail', 'name',
47+
'deaths', 'affected', 'damage_usd_thousands',
48+
'lat', 'lon'
49+
]
50+
51+
# Map disaster types to website format (lowercase, simplified)
52+
type_mapping = {
53+
'Flood': 'flood',
54+
'Storm': 'storm',
55+
'Drought': 'drought',
56+
'Wildfire': 'wildfire',
57+
'Earthquake': 'earthquake',
58+
'Volcanic activity': 'volcano',
59+
'Landslide': 'landslide',
60+
'Extreme temperature': 'drought', # Map to drought category
61+
'Mass movement (dry)': 'landslide', # Map to landslide category
62+
'Glacial lake outburst': 'flood', # Map to flood category
63+
'Fog': 'storm', # Map to storm category
64+
}
65+
66+
df_clean['type'] = df_clean['type'].map(type_mapping)
67+
68+
# Remove rows with unmapped disaster types
69+
before_filter = len(df_clean)
70+
df_clean = df_clean[df_clean['type'].notna()]
71+
print(f'Removed {before_filter - len(df_clean)} records with unmapped disaster types')
72+
73+
# Fill NaN values
74+
df_clean['name'] = df_clean['name'].fillna('Unnamed Event')
75+
df_clean['type_detail'] = df_clean['type_detail'].fillna('')
76+
df_clean['deaths'] = df_clean['deaths'].fillna(0)
77+
df_clean['affected'] = df_clean['affected'].fillna(0)
78+
df_clean['damage_usd_thousands'] = df_clean['damage_usd_thousands'].fillna(0)
79+
80+
# Save to CSV
81+
df_clean.to_csv(OUTPUT_FILE, index=False)
82+
83+
print(f'\n✓ Saved: {OUTPUT_FILE}')
84+
print(f'✓ Records: {len(df_clean):,}')
85+
print(f'✓ Year range: {int(df_clean["year"].min())}-{int(df_clean["year"].max())}')
86+
print(f'✓ Countries: {df_clean["iso"].nunique()}')
87+
88+
# Show disaster type distribution
89+
print('\nDisaster type distribution:')
90+
type_counts = df_clean['type'].value_counts()
91+
for dtype, count in type_counts.items():
92+
print(f' {dtype}: {count:,} ({count/len(df_clean)*100:.1f}%)')
93+
94+
print('\n✅ Done! The website can now load the data from emdat_clean.csv')

0 commit comments

Comments
 (0)