This commit is contained in:
parent
82c393408f
commit
aa0f6e5c03
4 changed files with 10826 additions and 3 deletions
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
|
|
@ -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,6 +117,8 @@ 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__":
|
||||
|
|
|
|||
10814
include/output/geo_plz_koordinaten.csv
Normal file
10814
include/output/geo_plz_koordinaten.csv
Normal file
File diff suppressed because it is too large
Load diff
BIN
tests/.DS_Store
vendored
Normal file
BIN
tests/.DS_Store
vendored
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue