fix kreise
Some checks failed
ETL-QS / etl-tests (push) Failing after 2s

This commit is contained in:
Pascal Beyer 2026-06-14 15:39:16 +02:00
parent 82c393408f
commit aa0f6e5c03
4 changed files with 10826 additions and 3 deletions

View file

@ -5,13 +5,13 @@
Lädt die deutschen PLZ-Koordinaten (Geokodierungs-Referenz) herunter und
erzeugt die Datei output/geo_plz_koordinaten.csv mit den Spalten:
plz, lat, lon, ort, bundesland
plz, lat, lon, ort, bundesland, kreis # NEU: kreis (Landkreis)
Primärquelle: GeoNames (https://download.geonames.org/export/zip/DE.zip)
Lizenz CC-BY 4.0 Quellenangabe "GeoNames" genügt.
Fallback: OpenPLZ API (https://openplzapi.org), falls GeoNames
nicht erreichbar ist (liefert keine Koordinaten, daher
nur als Notnagel für Ort/Bundesland).
nur als Notnagel für Ort/Bundesland/Kreis).
Aufruf: python 01_geodaten_holen.py
"""
@ -55,6 +55,9 @@ def lade_geonames() -> pd.DataFrame:
# Eine PLZ kann mehrere Orte/Ortsteile umfassen -> auf eine
# Koordinate je PLZ verdichten (Mittelpunkt), ersten Ort behalten.
# NEU: Landkreis wird mitgeführt. Hinweis: In seltenen Fällen liegt
# eine PLZ in mehreren Kreisen — dann gilt der häufigste Kreis der
# PLZ (Modus), was für die Kartendarstellung die beste Näherung ist.
geo = (
df.groupby("plz", as_index=False)
.agg(
@ -62,6 +65,8 @@ def lade_geonames() -> pd.DataFrame:
lon=("lon", "mean"),
ort=("ort", "first"),
bundesland=("bundesland", "first"),
kreis=("gemeinde", lambda s: s.mode().iat[0]
if not s.mode().empty else None),
)
)
geo["lat"] = geo["lat"].round(5)
@ -90,6 +95,8 @@ def lade_openplz_fallback() -> pd.DataFrame:
"lon": None,
"ort": item.get("name"),
"bundesland": (item.get("federalState") or {}).get("name"),
# NEU: Kreis auch im Fallback mitnehmen, soweit vorhanden
"kreis": (item.get("district") or {}).get("name"),
})
page += 1
if page > 400: # Sicherheitsbremse
@ -110,7 +117,9 @@ def main() -> None:
# Plausibilitätscheck: führende Nullen?
nullen = geo[geo["plz"].str.startswith("0")]
print(f" davon {len(nullen)} PLZ mit führender Null (z. B. {nullen['plz'].head(3).tolist()})")
# Plausibilitätscheck: Kreis-Abdeckung?
print(f" Kreis-Abdeckung: {geo['kreis'].notna().sum()}/{len(geo)} PLZ")
if __name__ == "__main__":
main()
main()

File diff suppressed because it is too large Load diff