Analyse historischer Hurricane-Tracks
Übersicht
Hurricanes gehören zu den Naturereignissen mit dem größten Schadenspotenzial. Dieses Projekt hat zum Ziel, das Hurricane-Risiko in den Vereinigten Staaten auf County-Ebene zu quantifizieren. Um dieses Ziel zu erreichen, ist es Eure Aufgabe, einen nicht-tabellarisch gespeicherten Datensatz zu Hurricane-Zugbahnen einzulesen und in einen räumlichen GIS-Vektordatensatz zu transformieren. Auf Basis einfacher Annahmen zu Durchmesser der Hurricanes, Immobilienwerten und Vulnerabilität wirst Du die mittleren jährlichen Schadenshöhen abschätzen, welche die Basis für die Berechnung von Versicherungsprämien sind.
Daten
- Die Daten für die Bearbeitung dieses Projekts sind auf Box.UP verfügbar (Link, Passwort: umweltdatenverarbeitung)
-
HURDAT2: Die neuesten Best Track Daten (HURDAT2) für den Atlantik gibt es auf der Seite https://www.nhc.noaa.gov/data/. Wir haben in dem Datensatz auf Box.UP unter
hurdat2/hurdat2-1851-2020-052921
bereits eine Datei für Euch bereitgestellt. Zusätzlich zu der Datei gibt es eine Formatbeschreibung als pdf (hurdat2/hurdat2-format-nov2019.pdf
). Das Dokument beschreibt das Format der Datei ausführlich und hilft Euch so, das Textformat zu interpretieren. Euer Ziel ist es zunächst, die Trackdaten in ein Geodatenformat zu überführen (in R mithilfe der Paketesf
odersp
, in Python mit Hilfe vongeopandas
). - Grenzen der US-Counties als Shapefile (
census/counties.shp
) und Zensusdaten (census/DataSet.xlsx
): Die Attributtabelle voncounties.shp
beihaltet die Spalte FIPS (eine ID für die Counties). Diese benötigt ihr, um die räumlichen Daten mit den Zensusdaten in der DateiDataSet.xlsx
zu verknüpfen. Aus dieser Exceldatei benötigt Ihr eigentlich nur die SpalteHSG495212
: der “Median value of owner-occupied housing units, 2008-2012”, vereinfacht gesagt der Median der Werte von Immobilienobjekten im jeweiligen County.
Ergebnisse
- eine Funktion, welche die HURDAT2-Daten einliest, und die mit zukünftig aktualisierten Daten ebenso funktionieren würde.
- Kartendarstellung der Hurricane-Zugbahnen
- Darstellung der Zeitreihen der Häufigkeit von Hurricanes von 1850 bis heute
- Risikoanalyse mit Kartendarstellung
Hinweise (für R)
-
Verwendet die Funktion readLines um die Daten einzulesen. Extrahiert für jedes gelistete Tiefdruckgebiet die Breiten- und Längegrade der Zugbahn und speichert sie als räumliches sf-Objekt ab (z.B. mit st_linestring(…)). Notiert zudem dabei, ob es sich bei einem der Tiefdruckgebiete auch um ein Hurricane handelt, am besten in einem data.frame. In der vierten Spalte gibt es den Eintrag HU, der diese Klassifizierung vornimmt. Kombiniert dann alle st_linestrings in eine Simple Feature Collection mittels st_sfc(…)). Fügt zum Schluss die Simple feature Collection mit dem data.frame zusammen mit Hilfe der Funktion st_sf().
-
Bei der Kombination der Bundesstaaten (die ihr am besten mit der Funktion st_read einlest) und der Zensusdaten sollte euch die Funktion merge helfen.
-
Um das Hurricane-Risiko zu berechnen, verwendet folgende Risikogleichung: R = HVA, wobei R das Risiko ($/y) ist, H die jährliche Häufigkeit von Hurricanes (1/y), V die Vulnerabilität (keine Einheit) und A die Werte ($), die der Naturgefahr ausgesetzt sind. Um H zu bestimmen, geht wie folgt vor: Nehmt einen charakteristischen Umfang eines Hurricanes an (z.B. 600 km). Erzeugt einen Buffer um die Hurricane Tracks (Achtung, hier wird der Radius benötigt). Berechnet für jedes County, wie häufig es von einem Hurricane getroffen wurde (z.B. st_intersects). Rechnet diese Werte in Häufigkeiten pro Jahr um. Um A zu bestimmen: Hier nehmen wir die Medianwerte der Immobilien im Zensusdatensatz. Um V zu bestimmen: Hier müssen wir kreativ sein, denn hier liegen uns keine Daten vor. Darum treffen wir hier einfach die Annahme, dass ein Hurricane zu Schaden am Haus führt, der 5% seines Wertes entspricht.
Hinweise für Python
Verarbeitung der HURDAT2-Daten
Es gibt wohl unendlich viele Möglichkeiten, mit der HURDAT2-Datei umzugehen - dabei kannst Du Dich so richtig mit Stringmethoden austoben. Falls Du aber Schwierigkeiten hast, hier ein Rezept:
- Lies zunächst die ganze Datei mit
read
als einen String ein. - Splitte diesen String mit dem Zeichen
\nAL
. Auf diese Weise erhältst Du eine Liste der einzelnen Sturmereignisse. -
Jetzt kommt der Trick: Du kannst nun jedes dieser Ereignisse als DateFrame “einlesen” und weiterverarbeiten. Auf folgende Weise kannst Du
pandas
vorgaukeln, dass es auf eine Datei zugreift, obwohl Du direkt einen String übergibst. Sagen wirstorm
ist ein beliebiges Listeneintrag aus dem obigen Split.import io data = io.StringIO(storm) df = pd.read_csv(data, sep=",", skiprows=1, header = None, dtype=str)
Das Argument
skiprows
verwendest Du, weil jedes Ereignis einen Header beinhaltet, den Du gesondert verarbeiten musst. Aus dem Header musst Du noch das Jahr und den Namen des Ereignisses extrahieren. Aus dem DataFrame brauchst Du eigentlich nur die ersten sechs Spalten (Datum, Zeit, Ereignis - z.B. Landfall, Status des Sturmsystems - z.B. Hurricane, Lat, Lon). Diese musst Du allerdings noch ein bisschen weiterverarbeiten. Vor allem Lat und und Lon müssen noch infloat
umgewandelt werden - dafür musst Du die nervigenN
,W
undE
loswerden. -
Jetzt kommt was Schönes: Sobald Du
df
zurechtgestutzt und saubergemacht hast, kannst Du den DataFrame in einenGeoDataFrame
mit der GeometrieLineString
umwandeln. Dafür mussdf
zwei Spalten mitlat
undlon
alsfloat
enthalten:from shapely.geometry import LineString ls = LineString(np.array(df[["lon","lat"]])) df = pd.DataFrame({"name":["IRENE"], "year": 2011, "geometry":ls}) gdf = gpd.GeoDataFrame(df, geometry="geometry", crs ="EPSG:4326")
-
Mit
gdf
hast Du somit einen GeoDataFrame für ein Hurricane-Ereignis. Du kannst alle Ereignisse wie folgt hintereinanderhängen:# Leerer Container tracks = gpd.GeoDataFrame({}, columns=["name", "id", "geometry"], crs="EPSG:4326") ... tracks = tracks.append(gdf)
Weiterer Umgang mit den Tracks
Sobald Du mit tracks
eine GeoDataFrame hast, der alle Hurricane-Tracks enthält, kannst Du damit die tollsten Sachen machen. Zum Beispiel einen Buffer anlegen. Zuvor musst Du Dir aber eine sinnvolle - möglichst längentreue - Projektion für die Sog. “Continuous US” raussuchen. Nur dann ergibt ein Buffer Sinn.
tracks = tracks.to_crs(...)
buftracks = tracks.buffer(distance=...)
Einlesen des County-Shapefiles und der Zensus-Daten
-
census/counties.shp
kannst Du einfach mitgeopandas.read_file
einlesen. Natürlich müssen sie in das gleiche CRS wie Deinetracks
gebracht werden. -
Um die Excel-Datei mit
pandas.read_excel
lesen zu können, musst Duopenpyxl
installieren:conda activate umweltdv conda install -c conda-forge openpyxl
- Für die Verknüpfung über die Spalte
FIPS
bzw.fips
muss Du zunächst dafür sorgen, dass die entsprechenden Spalten in beiden Datensätzen den gleichen Datentyp und den gleichen Spaltennamen haben. - Anschließend kannst Du mit
pd.merge(..., ..., on="fips")
verknüpfen.
Verschneidung der beiden Datensätze, Risikoanalyse
Jetzt kommt der zentrale inhaltliche Schritt: Du musst zählen, wie oft jedes County von einem Trackbuffer überdeckt wird. Lege dafür in Deine GeoDataFrame mit den counties (counties
) eine neue Spalte an (z.B. noverlaps
). Lege nun eine Schleife über alle tracks in buftracks
an und werte mittels counties.geometry.intersects(trackbuf)
aus. Zähle alle Überlappungen pro County zusammen. Die eigentliche Risikoanalyse ist dann nur noch ein schlapper Einzeiler:
{Mittlere Zahl der Überlappungen pro Jahr} * {Median des Gebäudewerts} * 0.05
Dieser Berechnung liegt die Annahme zugrunde, dass ein Hurricane an einem Gebäude im Mittel einen Schaden in Höhe von 5 Prozent des Gebäudewerts verursacht.
Jetzt noch ein paar schöne Karten dazu - fertig.