#!/usr/bin/env python
# coding: utf-8
# # Analyse der heissesten und kältesten Messstationen
# Dieses Notebook kann lokal oder **direkt im Browser** auf [](https://mybinder.org/v2/gh/meteotest/urban-heat-API-docs/data-analysis?labpath=python_data_analysis_hottest_coldest_locations.ipynb) oder [](https://colab.research.google.com/github/meteotest/urban-heat-API-docs/blob/data-analysis/python_data_analysis_hottest_coldest_locations.ipynb) ausgeführt werden.
# In[120]:
import requests
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt # for plotting
import folium
import branca
import math
# ## Berechnungen heisseste und kälteste Messstation
# In[ ]:
# Auswahl an Zeitraum (z.B. eine Hitzewelle, ein Monat, oder der ganze Sommer)
# Daten (UTC) als String in folgendem Format: "YYYY-MM-DDThh:mm:ssZ"
time_from = "2024-10-01T00:00:00Z"
time_to = "2024-10-11T23:59:59Z"
# Auswahl an Stationen
# Wenn alle Stationen berücksichtigt werden sollen, dann einfach die Liste leer lassen
# Hier ist eine Liste aller Stationen mit Name und ID: https://smart-urban-heat-map.ch/api/v2/latest
# station_ids = ["11001", "11002"] # Beispiel für nur eine Auswahl von zwei Stationen
station_ids = [] # Beispiel für alle Stationen
# In[ ]:
def get_stations() -> gpd.GeoDataFrame:
response = requests.get(
url=f"https://smart-urban-heat-map.ch/api/v2/latest"
)
stations = gpd.read_file(response.text)
return stations
def get_station_analysis_mean_temp(time_from: str, time_to: str, station_ids: [str]) -> pd.DataFrame:
stations = get_stations()
if station_ids:
stations = stations[stations["stationId"].isin(station_ids)]
time_from_dt = pd.to_datetime(time_from)
time_to_dt = pd.to_datetime(time_to)
time_difference = time_to_dt - time_from_dt
min_expected_values = round(time_difference.days * 24 * 2) # minimum two values per hour
stations["mean_temperature"] = None
stations["max_temperature"] = None
stations["date_of_max_temperature"] = None
stations["min_temperature"] = None
stations["date_of_min_temperature"] = None
for idx, station in stations.iterrows():
station_id = station.stationId
response = requests.get(url=f"https://smart-urban-heat-map.ch/api/v2/timeseries?stationId={station_id}&timeFrom={time_from}&timeTo={time_to}")
payload = response.json()
if payload["values"] is None or not len(payload["values"]):
stations = stations.drop(idx)
continue
if len(payload["values"]) < min_expected_values:
stations = stations.drop(idx)
continue
df = pd.DataFrame(payload["values"])
df["dateObserved"] = pd.to_datetime(df["dateObserved"])
df["dateObserved"] = df["dateObserved"].dt.tz_convert("Europe/Zurich")
# hier wird der mittelwert berechnet
mean_temperature = mean_temperatures(df)
# hier werden die min und max temperaturen berechnet
# und das jeweilige datum herausgeschrieben
min_temperature = min_temperatures(df)[0]
date_of_min_temperature = min_temperatures(df)[1]
max_temperature = max_temperatures(df)[0]
date_of_max_temperature = max_temperatures(df)[1]
# hier wird der mittelwert dem 'stations' dataframe hinzugefügt
stations.at[idx, "mean_temperature"] = mean_temperature
# hier werden der min und max temperatur sowie deren messdatum dem 'stations' dataframe hinzugefügt
stations.at[idx, "min_temperature"] = min_temperature
stations.at[idx, "date_of_min_temperature"] = date_of_min_temperature
stations.at[idx, "max_temperature"] = max_temperature
stations.at[idx, "date_of_max_temperature"] = date_of_max_temperature
return stations
def mean_temperatures(df: pd.DataFrame) -> float:
mean_temp = df.mean()["temperature"]
return mean_temp
def min_temperatures(df: pd.DataFrame) -> tuple[float,str]:
min_temp = df.min()["temperature"]
dateof_min_temp = df.loc[df['temperature'].idxmin()]['dateObserved']
return min_temp, dateof_min_temp
def max_temperatures(df: pd.DataFrame) -> tuple[float,str]:
max_temp = df.max()["temperature"]
dateof_max_temp = df.loc[df['temperature'].idxmax()]['dateObserved']
return max_temp, dateof_max_temp
# In[123]:
# Analyse der Temperatur laufen lassen
# Dies kann einige Sekunden / Minuten dauern, je nach ausgewähltem Zeitintervall
station_analysis = get_station_analysis_mean_temp(time_from, time_to, station_ids)
# In[132]:
# anzeigen aller stationen
station_analysis
# **Note**: Die Zeitstempel sind bereits von UTC zu UTC+2 (Central European Summer Time) konvertiert. Dies ist durch den Suffix "+02:00" nach dem Zeitwert angegeben.
#
# Beispiel:
# Der Zeitstempel *2024-08-02 17:57:10+02:00* bedeutet 17:57:10 in CEST (Schweizer Sommerzeit) und 15:57:10 in UTC time.
# ### Wärmste *n* Standorte herauslesen
# Definition: Standort mit höchster **mittlerer Temperatur** über den oben definierten Zeitraum.
# Hier muss für *n_warmest* eine Zahl eingegeben werden.
# In[124]:
# n wärmste Stationen auswählen
n_warmest = 3 # z.B. Wert 3 eingeben, um die wärmsten 3 Stationen anzuzeigen
# In[125]:
# Sortieren um die heissesten Stationen anzuzeigen
df_warm = station_analysis.sort_values(by='mean_temperature', ascending=False)[:n_warmest]
df_warm
# ### Kühlste *n* Standorte
# Definition: Standort mit tiefster **mittlerer Temperatur** über den oben definierten Zeitraum.
# Hier muss für *c_coldest* eine Zahl eingegeben werden.
# In[126]:
# n kälteste Stationen auswählen
n_coldest = 3 # z.B. Wert 3 eingeben, um die kältesten 3 Stationen anzuzeigen
# In[127]:
# Sortieren um die kältesten Stationen anzuzeigen
df_cold = station_analysis.sort_values(by='mean_temperature', ascending=True)[:n_coldest]
df_cold
# ## Karte der mittleren Temperaturen pro Messstation
# In[133]:
# mean_temperature Map
m = folium.Map(location=[station_analysis.geometry.y.mean(), station_analysis.geometry.x.mean()], zoom_start=13, tiles="CartoDB positron")
# Add a fixed title to the map
title_html = f'''