Files
energy_price_model_prediction/jaar_weerdata.py
2025-11-13 08:42:21 +01:00

365 lines
12 KiB
Python

"""
Script voor het ophalen van een HEEL JAAR aan historische weerdata voor Amersfoort
"""
import requests
import sqlite3
import pandas as pd
from datetime import datetime
import time
# ===== CONFIGURATIE =====
LOCATIE = "Amersfoort"
LATITUDE = 52.15
LONGITUDE = 5.39
# Kies je jaar(en) hier!
START_JAAR = 2025
START_MAAND = 1
START_DAG = 1
EIND_JAAR = 2025
EIND_MAAND = 11
EIND_DAG = 11
DATABASE_NAAM = f"weer_amersfoort_{START_JAAR}.db"
# Open-Meteo kan maximaal 1 jaar per request, dus we splitsen het op indien nodig
# ========================
def setup_database(db_naam):
"""Maak database en tabellen aan"""
conn = sqlite3.connect(db_naam)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS weer_dagelijks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
datum DATE UNIQUE NOT NULL,
locatie TEXT NOT NULL,
latitude REAL,
longitude REAL,
temp_max REAL,
temp_min REAL,
temp_gem REAL,
neerslag REAL,
wind_max REAL,
wind_gem REAL,
wind_richting REAL,
luchtvochtigheid_gem REAL,
bewolking_gem REAL,
zonuren REAL,
toegevoegd_op TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS weer_uurlijks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
datum_tijd DATETIME UNIQUE NOT NULL,
locatie TEXT NOT NULL,
temperatuur REAL,
gevoelstemperatuur REAL,
neerslag REAL,
wind_snelheid REAL,
wind_richting REAL,
luchtvochtigheid INTEGER,
bewolking INTEGER,
luchtdruk REAL,
toegevoegd_op TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
return conn
def haal_weerdata_op(start_date, end_date, ophaal_uurlijks=True):
"""
Haal weerdata op via Open-Meteo API
Args:
start_date: datetime object voor startdatum
end_date: datetime object voor einddatum
ophaal_uurlijks: Ook uurlijkse data ophalen (kan veel data zijn!)
"""
url = "https://archive-api.open-meteo.com/v1/archive"
# Uitgebreide parameters voor een volledig beeld
params = {
"latitude": LATITUDE,
"longitude": LONGITUDE,
"start_date": start_date.strftime("%Y-%m-%d"),
"end_date": end_date.strftime("%Y-%m-%d"),
"daily": [
"temperature_2m_max",
"temperature_2m_min",
"temperature_2m_mean",
"apparent_temperature_max",
"apparent_temperature_min",
"precipitation_sum",
"rain_sum",
"snowfall_sum",
"precipitation_hours",
"wind_speed_10m_max",
"wind_speed_10m_mean",
"wind_direction_10m_dominant",
"sunshine_duration"
],
"timezone": "Europe/Amsterdam"
}
if ophaal_uurlijks:
params["hourly"] = [
"temperature_2m",
"apparent_temperature",
"precipitation",
"rain",
"snowfall",
"wind_speed_10m",
"wind_direction_10m",
"relative_humidity_2m",
"cloud_cover",
"surface_pressure"
]
print(f"\n📡 Data ophalen voor periode: {start_date.date()} tot {end_date.date()}")
print(f" Aantal dagen: {(end_date - start_date).days + 1}")
try:
response = requests.get(url, params=params, timeout=60)
response.raise_for_status()
print(f"✅ Data succesvol opgehaald!")
return response.json()
except requests.exceptions.RequestException as e:
print(f"❌ Fout bij ophalen data: {e}")
return None
def sla_dagelijkse_data_op(conn, data):
"""Sla dagelijkse data op in database"""
if not data or 'daily' not in data:
return 0
daily = data['daily']
cursor = conn.cursor()
records_toegevoegd = 0
for i in range(len(daily['time'])):
try:
cursor.execute('''
INSERT OR REPLACE INTO weer_dagelijks
(datum, locatie, latitude, longitude, temp_max, temp_min,
temp_gem, neerslag, wind_max, wind_gem, wind_richting,
zonuren)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (
daily['time'][i],
LOCATIE,
LATITUDE,
LONGITUDE,
daily['temperature_2m_max'][i],
daily['temperature_2m_min'][i],
daily['temperature_2m_mean'][i],
daily['precipitation_sum'][i],
daily['wind_speed_10m_max'][i],
daily['wind_speed_10m_mean'][i],
daily['wind_direction_10m_dominant'][i],
daily['sunshine_duration'][i] / 3600 if daily['sunshine_duration'][i] else None # Convert seconds to hours
))
records_toegevoegd += 1
except sqlite3.IntegrityError:
pass
conn.commit()
return records_toegevoegd
def sla_uurlijkse_data_op(conn, data):
"""Sla uurlijkse data op in database"""
if not data or 'hourly' not in data:
return 0
hourly = data['hourly']
cursor = conn.cursor()
records_toegevoegd = 0
print(f" Uurlijkse records verwerken: {len(hourly['time'])} uur...")
# Batch insert voor betere performance
batch = []
for i in range(len(hourly['time'])):
batch.append((
hourly['time'][i],
LOCATIE,
hourly['temperature_2m'][i],
hourly['apparent_temperature'][i],
hourly['precipitation'][i],
hourly['wind_speed_10m'][i],
hourly['wind_direction_10m'][i],
hourly['relative_humidity_2m'][i],
hourly['cloud_cover'][i],
hourly['surface_pressure'][i]
))
cursor.executemany('''
INSERT OR REPLACE INTO weer_uurlijks
(datum_tijd, locatie, temperatuur, gevoelstemperatuur, neerslag,
wind_snelheid, wind_richting, luchtvochtigheid, bewolking, luchtdruk)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', batch)
conn.commit()
return len(batch)
def toon_statistieken(conn):
"""Toon statistieken van de database"""
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM weer_dagelijks")
aantal_dagen = cursor.fetchone()[0]
cursor.execute("SELECT COUNT(*) FROM weer_uurlijks")
aantal_uren = cursor.fetchone()[0]
print("\n" + "="*70)
print("DATABASE STATISTIEKEN")
print("="*70)
print(f"📊 Dagelijkse records: {aantal_dagen} dagen")
print(f"📊 Uurlijkse records: {aantal_uren} uur")
if aantal_dagen > 0:
cursor.execute("""
SELECT
MIN(datum) as eerste_datum,
MAX(datum) as laatste_datum,
ROUND(AVG(temp_max), 1) as gem_max_temp,
ROUND(MAX(temp_max), 1) as hoogste_temp,
ROUND(MIN(temp_min), 1) as laagste_temp,
ROUND(SUM(neerslag), 1) as totale_neerslag,
ROUND(AVG(wind_max), 1) as gem_wind,
ROUND(SUM(zonuren), 1) as totale_zonuren
FROM weer_dagelijks
""")
stats = cursor.fetchone()
print(f"\n📅 Periode: {stats[0]} tot {stats[1]}")
print(f"\n🌡️ TEMPERATUUR:")
print(f" Gemiddeld max: {stats[2]}°C")
print(f" Hoogste: {stats[3]}°C")
print(f" Laagste: {stats[4]}°C")
print(f"\n💧 NEERSLAG:")
print(f" Totaal: {stats[5]} mm")
print(f"\n💨 WIND:")
print(f" Gemiddeld max: {stats[6]} km/h")
print(f"\n☀️ ZON:")
print(f" Totale zonuren: {stats[7]} uur ({stats[7]/24:.1f} dagen)")
# Maandstatistieken
print(f"\n📊 PER MAAND:")
cursor.execute("""
SELECT
strftime('%Y-%m', datum) as maand,
ROUND(AVG(temp_max), 1) as gem_max,
ROUND(AVG(temp_min), 1) as gem_min,
ROUND(SUM(neerslag), 1) as neerslag,
COUNT(CASE WHEN neerslag > 0.1 THEN 1 END) as regendagen
FROM weer_dagelijks
GROUP BY maand
ORDER BY maand
""")
print(f"\n {'Maand':<10} {'Max°C':<8} {'Min°C':<8} {'Neerslag':<12} {'Regendagen':<12}")
print(f" {'-'*60}")
for row in cursor.fetchall():
print(f" {row[0]:<10} {row[1]:<8} {row[2]:<8} {row[3]:<12} {row[4]:<12}")
print("="*70)
def exporteer_naar_csv(conn, output_prefix="weer_export"):
"""Exporteer data naar CSV bestanden"""
# Dagelijkse data
df_dagelijks = pd.read_sql_query(
"SELECT * FROM weer_dagelijks ORDER BY datum",
conn
)
csv_dag = f"{output_prefix}_dagelijks.csv"
df_dagelijks.to_csv(csv_dag, index=False)
print(f"✅ Dagelijkse data: {csv_dag} ({len(df_dagelijks)} records)")
# Uurlijkse data (alleen als niet te groot)
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM weer_uurlijks")
aantal_uur = cursor.fetchone()[0]
if aantal_uur > 0 and aantal_uur < 10000: # Max ~1 jaar uurlijks
df_uurlijks = pd.read_sql_query(
"SELECT * FROM weer_uurlijks ORDER BY datum_tijd",
conn
)
csv_uur = f"{output_prefix}_uurlijks.csv"
df_uurlijks.to_csv(csv_uur, index=False)
print(f"✅ Uurlijkse data: {csv_uur} ({len(df_uurlijks)} records)")
elif aantal_uur > 10000:
print(f"⚠️ Uurlijkse data ({aantal_uur} records) niet geëxporteerd (te groot)")
def main():
"""Hoofdfunctie"""
print("="*70)
print(f"HISTORISCHE WEERDATA VOOR {LOCATIE}")
print("="*70)
# Datum objecten maken
start_date = datetime(START_JAAR, START_MAAND, START_DAG)
end_date = datetime(EIND_JAAR, EIND_MAAND, EIND_DAG)
# Check of periode niet te groot is
dagen = (end_date - start_date).days + 1
if dagen > 400:
antwoord = input(f"\n⚠️ Je wilt {dagen} dagen ophalen. Dit kan even duren. Doorgaan? (j/n): ")
if antwoord.lower() != 'j':
print("Geannuleerd.")
return
# Uurlijkse data vraag
if dagen > 180:
print(f"\n💡 TIP: Voor {dagen} dagen is dat {dagen*24} uur aan data.")
ophaal_uurlijks = input(" Wil je ook uurlijkse data? Dit maakt de database groter. (j/n): ")
ophaal_uurlijks = ophaal_uurlijks.lower() == 'j'
else:
ophaal_uurlijks = True
# Setup database
print(f"\n📁 Database: {DATABASE_NAAM}")
conn = setup_database(DATABASE_NAAM)
# Haal data op
data = haal_weerdata_op(start_date, end_date, ophaal_uurlijks)
if data:
print("\n💾 Data opslaan in database...")
# Dagelijkse data
dag_records = sla_dagelijkse_data_op(conn, data)
print(f"{dag_records} dagelijkse records opgeslagen")
# Uurlijkse data
if ophaal_uurlijks:
uur_records = sla_uurlijkse_data_op(conn, data)
print(f"{uur_records} uurlijkse records opgeslagen")
# Statistieken
toon_statistieken(conn)
# Exporteer
print(f"\n📤 Data exporteren...")
exporteer_naar_csv(conn, f"amersfoort_{START_JAAR}")
conn.close()
print(f"\n✅ Klaar! Database opgeslagen als: {DATABASE_NAAM}")
if __name__ == "__main__":
print("\n💡 Open-Meteo API - Gratis historische weerdata")
print(" Data beschikbaar vanaf 1940")
print(" Geen API key nodig!\n")
main()