pip install wetterdienst
import warnings
warnings.filterwarnings("ignore")
from wetterdienst.provider.dwd.observation import DwdObservationRequest, \
DwdObservationPeriod, DwdObservationResolution, DwdObservationParameter, DwdObservationDataset
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
Which parameters are available?
# all
print("All available parameters")
print(
DwdObservationRequest.discover()
)
# selection
print("Selection of daily data")
print(
DwdObservationRequest.discover(
filter_=DwdObservationResolution.DAILY
)
)
All available parameters
{
"MINUTE_1": [
"PRECIPITATION_HEIGHT",
"PRECIPITATION_HEIGHT_DROPLET",
"PRECIPITATION_HEIGHT_ROCKER",
"PRECIPITATION_FORM"
],
"MINUTE_10": [
"PRESSURE_AIR_STATION_HEIGHT",
"TEMPERATURE_AIR_200",
"TEMPERATURE_AIR_005",
"HUMIDITY",
"TEMPERATURE_DEW_POINT_200",
"TEMPERATURE_AIR_MAX_200",
"TEMPERATURE_AIR_MAX_005",
"TEMPERATURE_AIR_MIN_200",
"TEMPERATURE_AIR_MIN_005",
"WIND_GUST_MAX",
"WIND_SPEED_MIN",
"WIND_SPEED_ROLLING_MEAN_MAX",
"WIND_DIRECTION_MAX_VELOCITY",
"PRECIPITATION_DURATION",
"PRECIPITATION_HEIGHT",
"PRECIPITATION_INDICATOR_WR",
"RADIATION_SKY_DIFFUSE",
"RADIATION_GLOBAL",
"SUNSHINE_DURATION",
"RADIATION_SKY_LONG_WAVE",
"WIND_SPEED",
"WIND_DIRECTION"
],
"HOURLY": [
"TEMPERATURE_AIR_200",
"HUMIDITY",
"CLOUD_COVER_TOTAL",
"CLOUD_COVER_TOTAL_INDICATOR",
"CLOUD_TYPE_LAYER1",
"CLOUD_TYPE_LAYER1_ABBREVIATION",
"CLOUD_HEIGHT_LAYER1",
"CLOUD_COVER_LAYER1",
"CLOUD_TYPE_LAYER2",
"CLOUD_TYPE_LAYER2_ABBREVIATION",
"CLOUD_HEIGHT_LAYER2",
"CLOUD_COVER_LAYER2",
"CLOUD_TYPE_LAYER3",
"CLOUD_TYPE_LAYER3_ABBREVIATION",
"CLOUD_HEIGHT_LAYER3",
"CLOUD_COVER_LAYER3",
"CLOUD_TYPE_LAYER4",
"CLOUD_TYPE_LAYER4_ABBREVIATION",
"CLOUD_HEIGHT_LAYER4",
"CLOUD_COVER_LAYER4",
"TEMPERATURE_DEW_POINT_200",
"PRECIPITATION_HEIGHT",
"PRECIPITATION_INDICATOR",
"PRECIPITATION_FORM",
"PRESSURE_AIR_SEA_LEVEL",
"PRESSURE_AIR_STATION_HEIGHT",
"TEMPERATURE_SOIL_002",
"TEMPERATURE_SOIL_005",
"TEMPERATURE_SOIL_010",
"TEMPERATURE_SOIL_020",
"TEMPERATURE_SOIL_050",
"TEMPERATURE_SOIL_100",
"END_OF_INTERVAL",
"RADIATION_SKY_LONG_WAVE",
"RADIATION_SKY_SHORT_WAVE_DIFFUSE",
"RADIATION_GLOBAL",
"SUNSHINE_DURATION",
"SUN_ZENITH",
"TRUE_LOCAL_TIME",
"VISIBILITY_INDICATOR",
"VISIBILITY",
"WIND_SPEED",
"WIND_DIRECTION"
],
"SUBDAILY": [
"TEMPERATURE_AIR_200",
"HUMIDITY",
"CLOUD_COVER_TOTAL",
"CLOUD_DENSITY",
"PRESSURE_VAPOR",
"TEMPERATURE_AIR_005",
"PRESSURE_AIR",
"TEMPERATURE_SOIL_005",
"VISIBILITY",
"WIND_DIRECTION",
"WIND_FORCE_BEAUFORT"
],
"DAILY": [
"WIND_GUST_MAX",
"WIND_SPEED",
"PRECIPITATION_HEIGHT",
"PRECIPITATION_FORM",
"SUNSHINE_DURATION",
"SNOW_DEPTH",
"CLOUD_COVER_TOTAL",
"PRESSURE_VAPOR",
"PRESSURE_AIR",
"TEMPERATURE_AIR_200",
"HUMIDITY",
"TEMPERATURE_AIR_MAX_200",
"TEMPERATURE_AIR_MIN_200",
"TEMPERATURE_AIR_MIN_005",
"SNOW_DEPTH_NEW",
"TEMPERATURE_SOIL_002",
"TEMPERATURE_SOIL_005",
"TEMPERATURE_SOIL_010",
"TEMPERATURE_SOIL_020",
"TEMPERATURE_SOIL_050",
"RADIATION_SKY_LONG_WAVE",
"RADIATION_SKY_SHORT_WAVE_DIFFUSE",
"RADIATION_SKY_SHORT_WAVE_DIRECT",
"SNOW_DEPTH_EXCELLED",
"WATER_EQUIVALENT_TOTAL_SNOW_DEPTH",
"WATER_EQUIVALENT_SNOW",
"FOG",
"THUNDER",
"STORM_STRONG_WIND",
"STORM_STORMIER_WIND",
"DEW",
"GLAZE",
"RIPE",
"SLEET",
"HAIL"
],
"MONTHLY": [
"CLOUD_COVER_TOTAL",
"TEMPERATURE_AIR_200",
"TEMPERATURE_AIR_MAX_MEAN_200",
"TEMPERATURE_AIR_MIN_MEAN_200",
"WIND_FORCE_BEAUFORT",
"TEMPERATURE_AIR_MAX_200",
"WIND_GUST_MAX",
"TEMPERATURE_AIR_MIN_200",
"SUNSHINE_DURATION",
"PRECIPITATION_HEIGHT",
"PRECIPITATION_HEIGHT_MAX",
"SNOW_DEPTH_NEW",
"SNOW_DEPTH",
"STORM_STRONG_WIND",
"STORM_STORMIER_WIND",
"THUNDER",
"GLAZE",
"SLEET",
"HAIL",
"FOG",
"DEW"
],
"ANNUAL": [
"CLOUD_COVER_TOTAL",
"TEMPERATURE_AIR_200",
"TEMPERATURE_AIR_MAX_MEAN_200",
"TEMPERATURE_AIR_MIN_MEAN_200",
"WIND_FORCE_BEAUFORT",
"SUNSHINE_DURATION",
"WIND_GUST_MAX",
"TEMPERATURE_AIR_MAX_200",
"TEMPERATURE_AIR_MIN_200",
"PRECIPITATION_HEIGHT",
"PRECIPITATION_HEIGHT_MAX",
"SNOW_DEPTH_NEW",
"SNOW_DEPTH",
"STORM_STRONG_WIND",
"STORM_STORMIER_WIND",
"THUNDER",
"GLAZE",
"SLEET",
"HAIL",
"FOG",
"DEW"
]
}
Selection of daily data
{
"DAILY": [
"WIND_GUST_MAX",
"WIND_SPEED",
"PRECIPITATION_HEIGHT",
"PRECIPITATION_FORM",
"SUNSHINE_DURATION",
"SNOW_DEPTH",
"CLOUD_COVER_TOTAL",
"PRESSURE_VAPOR",
"PRESSURE_AIR",
"TEMPERATURE_AIR_200",
"HUMIDITY",
"TEMPERATURE_AIR_MAX_200",
"TEMPERATURE_AIR_MIN_200",
"TEMPERATURE_AIR_MIN_005",
"SNOW_DEPTH_NEW",
"TEMPERATURE_SOIL_002",
"TEMPERATURE_SOIL_005",
"TEMPERATURE_SOIL_010",
"TEMPERATURE_SOIL_020",
"TEMPERATURE_SOIL_050",
"RADIATION_SKY_LONG_WAVE",
"RADIATION_SKY_SHORT_WAVE_DIFFUSE",
"RADIATION_SKY_SHORT_WAVE_DIRECT",
"SNOW_DEPTH_EXCELLED",
"WATER_EQUIVALENT_TOTAL_SNOW_DEPTH",
"WATER_EQUIVALENT_SNOW",
"FOG",
"THUNDER",
"STORM_STRONG_WIND",
"STORM_STORMIER_WIND",
"DEW",
"GLAZE",
"RIPE",
"SLEET",
"HAIL"
]
}
(here we pick historical daily precipitation - hdp)
request = DwdObservationRequest(
parameter=DwdObservationDataset.PRECIPITATION_MORE,
resolution=DwdObservationResolution.DAILY,
period=DwdObservationPeriod.HISTORICAL
)
print("Number of stations with available data: ", request.all().df.sum())
print("Some of the stations:")
request.all().df.head()
Number of stations with available data: station_id 0000100002000030000400006000070000800009000100... height 1614425.0 latitude 285344.8849 longitude 58614.3066 station_name AachAachen (Kläranlage)AachenAachen-BrandAalen... state Baden-WürttembergNordrhein-WestfalenNordrhein-... dtype: object Some of the stations:
| station_id | from_date | to_date | height | latitude | longitude | station_name | state | |
|---|---|---|---|---|---|---|---|---|
| 0 | 00001 | 1912-01-01 00:00:00+00:00 | 1986-06-30 00:00:00+00:00 | 478.0 | 47.8413 | 8.8493 | Aach | Baden-Württemberg |
| 1 | 00002 | 1951-01-01 00:00:00+00:00 | 2006-12-31 00:00:00+00:00 | 138.0 | 50.8066 | 6.0996 | Aachen (Kläranlage) | Nordrhein-Westfalen |
| 2 | 00003 | 1891-01-01 00:00:00+00:00 | 2011-03-31 00:00:00+00:00 | 202.0 | 50.7827 | 6.0941 | Aachen | Nordrhein-Westfalen |
| 3 | 00004 | 1951-01-01 00:00:00+00:00 | 1979-10-31 00:00:00+00:00 | 243.0 | 50.7683 | 6.1207 | Aachen-Brand | Nordrhein-Westfalen |
| 4 | 00006 | 1982-11-01 00:00:00+00:00 | 2021-03-26 00:00:00+00:00 | 455.0 | 48.8361 | 10.0598 | Aalen-Unterrombach | Baden-Württemberg |
The metadata includes an id, the range of the measurements, the position (including height) as well as place and state of it and if it has a file. With the following plot we want to show a map of those stations:
cmap = cm.get_cmap('viridis')
bounds = request.all().df.height.quantile([0, 0.25, 0.5, 0.75, 1]).values
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
fig, ax = plt.subplots(figsize=(10, 10))
plot = request.all().df.plot.scatter(
x="longitude", y="latitude", c="height", cmap=cmap, norm=norm, ax=ax)
plot.set_title("Map of daily precipitation stations in Germany\n"
"Color refers to height of station")
plt.show()
Let's get some data for the above request
print("Receiving historical daily climate data for Dresden-Klotzsche (1048)")
station_data = request.filter(station_id=[1048]).values.all().df
station_data.dropna(axis=0).head()
100%|██████████| 1/1 [00:00<00:00, 1.41it/s]
Receiving historical daily climate data for Dresden-Klotzsche (1048)
| station_id | date | dataset | parameter | value | quality | |
|---|---|---|---|---|---|---|
| 0 | 01048 | 1926-04-25 00:00:00+00:00 | precipitation_more | rs | 0.0 | 1 |
| 1 | 01048 | 1926-04-26 00:00:00+00:00 | precipitation_more | rs | 0.0 | 1 |
| 2 | 01048 | 1926-04-27 00:00:00+00:00 | precipitation_more | rs | 0.0 | 1 |
| 3 | 01048 | 1926-04-28 00:00:00+00:00 | precipitation_more | rs | 0.0 | 1 |
| 4 | 01048 | 1926-04-29 00:00:00+00:00 | precipitation_more | rs | 0.0 | 1 |
See that DATE is already parsed, so we can easily get some nice graphs with matplotlib, which we will do in the next part. We can also request direct parameters from the given parameter sets. We know that CLIMATE_SUMMARY contains TMK, TNK, TXK and RSK, so let's request those. This option will automatically tidy the data.
print("Receiving historical daily temperature and precipitation for Dresden-Klotzsche "
"(1048).")
request = DwdObservationRequest(
parameter=[
DwdObservationParameter.DAILY.TEMPERATURE_AIR_200,
DwdObservationParameter.DAILY.TEMPERATURE_AIR_MAX_200,
DwdObservationParameter.DAILY.TEMPERATURE_AIR_MIN_200,
DwdObservationParameter.DAILY.PRECIPITATION_HEIGHT
],
resolution=DwdObservationResolution.DAILY,
period=DwdObservationPeriod.HISTORICAL
).filter(station_id=(1048, ))
station_data = request.values.all().df
station_data.dropna(axis=0).head()
Receiving historical daily temperature and precipitation for Dresden-Klotzsche (1048).
100%|██████████| 1/1 [00:02<00:00, 2.62s/it]
| station_id | date | dataset | parameter | value | quality | |
|---|---|---|---|---|---|---|
| 0 | 01048 | 1934-01-01 00:00:00+00:00 | climate_summary | temperature_air_200 | 0.5 | 1 |
| 1 | 01048 | 1934-01-02 00:00:00+00:00 | climate_summary | temperature_air_200 | -0.1 | 1 |
| 2 | 01048 | 1934-01-03 00:00:00+00:00 | climate_summary | temperature_air_200 | -0.7 | 1 |
| 3 | 01048 | 1934-01-04 00:00:00+00:00 | climate_summary | temperature_air_200 | -1.6 | 1 |
| 4 | 01048 | 1934-01-05 00:00:00+00:00 | climate_summary | temperature_air_200 | 0.9 | 1 |
Now that we have data, let's create some plots! We can create a time series/histogram of the temperatures and precipitation
cmap = plt.get_cmap('viridis', 4)
colors = cmap.colors
PARAMETERS = ["tnk", "tmk", "txk", "rsk"]
station_data_grouped = station_data.groupby(station_data["parameter"], observed=True)
fig, axes = plt.subplots(nrows=len(PARAMETERS), tight_layout=True, figsize=(10, 40))
for (parameter, group), ax, color in zip(station_data_grouped, axes, colors):
group.plot(x="date", y="value", label=parameter, alpha=.75, ax=ax, c=color)
plt.tight_layout()
plt.subplots_adjust(top=0.9)
plt.suptitle("Temperature and precipitation time series of Dresden, Germany")
plt.show()
import numpy as np
import pandas as pd
station_data_yearly = []
for (year, parameter), group in station_data.groupby(
[station_data["date"].dt.year, "parameter"], as_index=False, observed=True):
if parameter == "rsk":
station_data_yearly.append(group.dropna().agg({"value": np.sum}))
else:
station_data_yearly.append(group.dropna().agg({"value": np.mean}))
station_data_yearly = pd.concat(station_data_yearly)
station_data_yearly
value 2.705976
value 2.040000
value 1.729235
value 1.808493
value 2.591233
...
value 1.153699
value 11.229041
value 15.583836
value 6.808493
value 1.378904
Length: 296, dtype: float64
To find a station near to a certain area, call nearby_number().
DwdObservationRequest(
parameter=DwdObservationDataset.CLIMATE_SUMMARY,
resolution=DwdObservationResolution.DAILY,
period=DwdObservationPeriod.HISTORICAL,
start_date="2000-01-01",
end_date="2010-01-01"
).nearby_number(
51.05089,
13.73832,
5
).df
start_date and end_date filtering limited to defined periods [<Period.HISTORICAL: 'historical'>]
| station_id | from_date | to_date | height | latitude | longitude | station_name | state | distance_to_location | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 01047 | 1828-01-01 00:00:00+00:00 | 1915-12-31 00:00:00+00:00 | 112.0 | 51.0557 | 13.7274 | Dresden (Mitte) | Sachsen | 1.326824 |
| 1 | 01051 | 1936-01-01 00:00:00+00:00 | 2021-03-26 00:00:00+00:00 | 120.0 | 51.0248 | 13.7750 | Dresden-Strehlen | Sachsen | 5.005144 |
| 2 | 01048 | 1934-01-01 00:00:00+00:00 | 2021-03-26 00:00:00+00:00 | 227.0 | 51.1280 | 13.7543 | Dresden-Klotzsche | Sachsen | 8.756424 |
| 3 | 05282 | 1917-01-01 00:00:00+00:00 | 1974-06-30 00:00:00+00:00 | 246.0 | 51.1197 | 13.6744 | Wahnsdorf bei Dresden | Sachsen | 10.443200 |
| 4 | 01050 | 1949-01-01 00:00:00+00:00 | 2021-03-26 00:00:00+00:00 | 112.0 | 51.0221 | 13.8470 | Dresden-Hosterwitz | Sachsen | 12.501498 |