Tilføj koordinater til en CSV-fil
Geokod en liste af adresser til x/y i WGS84 eller UTM32 med datavask og opslag på id, i ren Python eller med pandas.
Et kort over kunder, en ruteplan eller en analyse pr. område kræver koordinater på hver adresse. Har du en CSV med vejnavn, husnummer og postnummer, kan du tilføje kolonnerne x og y med to slags kald: datavask finder adressens id, og et opslag på id'et giver koordinaterne.
Koordinaterne hører til adgangsadressen, altså bygningens indgang. Alle lejligheder i samme opgang har derfor samme punkt, og du kan geokode på bygningsniveau uden etage og dør.
1. Find adgangsadressen med datavask
GET /datavask/adgangsadresser tager vejnavn, husnummer og postnummer (eller hele adressen i betegnelse) og returnerer det bedste match med id:
curl -s -G "https://api.danadresse.dk/datavask/adgangsadresser" \ --data-urlencode "vejnavn=Strandvejen" \ --data-urlencode "husnr=100" \ --data-urlencode "postnr=2900" \ -H "X-Api-Key: $DANADRESSE_API_KEY"
I svaret er resultater[0].adresse.id adgangsadressens id. Svaret har samme form som DAWA's datavask og indeholder ingen koordinater. Tag kun rækker med kategori A eller B. En C-række får tomme koordinater, så et menneske kan se på den.
2. Hent koordinaterne på id
GET /adgangsadresser tager flere id'er adskilt af |. Med struktur=mini får du et fladt objekt med x og y. Uden srid er de længde- og breddegrad i WGS84 med otte decimaler. Med srid=25832 er de i UTM32-meter, som er praktisk til afstande og GIS:
curl -s -G "https://api.danadresse.dk/adgangsadresser" \ --data-urlencode "id=0a3f507c-0624-32b8-e044-0003ba298018|0a3f507a-ec01-32b8-e044-0003ba298018" \ --data-urlencode "struktur=mini" \ --data-urlencode "srid=25832" \ -H "X-Api-Key: $DANADRESSE_API_KEY"
Svaret kommer ikke i samme rækkefølge som id'erne. Slå op på id, ikke på position. Hold dig til omkring 100 id'er pr. kald, så URL'en ikke bliver for lang.
Vil du have begge koordinatsystemer i ét kald, så tilføj format=csv. CSV-svaret har altid kolonnerne wgs84koordinat_længde, wgs84koordinat_bredde, etrs89koordinat_øst og etrs89koordinat_nord.
3. Hele flowet med csv-modulet
Eksemplet læser to rækker fra en tekststreng, vasker dem og henter koordinaterne i WGS84 og UTM32 med ét kald pr. koordinatsystem. Det bruger kun requests og standardbiblioteket:
import csv import io import os import sys import requests DATA = """kundenr,vejnavn,husnr,postnr 1001,Strandvejen,100,2900 1002,Rådhuspladsen,1,1550 """ s = requests.Session() s.headers["X-Api-Key"] = os.environ["DANADRESSE_API_KEY"] API = "https://api.danadresse.dk" rows = list(csv.DictReader(io.StringIO(DATA))) for row in rows: r = s.get(f"{API}/datavask/adgangsadresser", timeout=10, params={ "vejnavn": row["vejnavn"], "husnr": row["husnr"], "postnr": row["postnr"]}) r.raise_for_status() svar = r.json() ok = svar["kategori"] in ("A", "B") and svar["resultater"] row["kategori"] = svar["kategori"] row["adgangsadresseid"] = svar["resultater"][0]["adresse"]["id"] if ok else "" ids = [r["adgangsadresseid"] for r in rows if r["adgangsadresseid"]] def punkter(srid): r = s.get(f"{API}/adgangsadresser", timeout=10, params={ "id": "|".join(ids), "struktur": "mini", "srid": srid, "per_side": len(ids)}) r.raise_for_status() return {a["id"]: (a["x"], a["y"]) for a in r.json()} wgs84, utm = punkter(4326), punkter(25832) for row in rows: aid = row["adgangsadresseid"] row["lon"], row["lat"] = wgs84.get(aid, ("", "")) row["x_utm"], row["y_utm"] = utm.get(aid, ("", "")) out = csv.DictWriter(sys.stdout, fieldnames=list(rows[0].keys())) out.writeheader() out.writerows(rows)
Til en rigtig fil skal du udskifte io.StringIO(DATA) med open("kunder.csv", encoding="utf-8-sig"), dele id-listen op i bidder af 100 og håndtere 429 som beskrevet i Grænser, kvoter og 429.
4. Samme med pandas
Med pandas er det praktisk at vaske de unikke adresser én gang, hente koordinaterne i bunker af 100 id'er og flette resultatet tilbage. Mange CRM-eksporter har den samme adresse på flere kunder:
import os import pandas as pd import requests s = requests.Session() s.headers["X-Api-Key"] = os.environ["DANADRESSE_API_KEY"] df = pd.read_csv("kunder.csv", dtype=str, encoding="utf-8-sig") unikke = df[["vejnavn", "husnr", "postnr"]].drop_duplicates() def vask(r): svar = s.get("https://api.danadresse.dk/datavask/adgangsadresser", timeout=10, params={"vejnavn": r.vejnavn, "husnr": r.husnr, "postnr": r.postnr}).json() ok = svar["kategori"] in ("A", "B") and svar["resultater"] return pd.Series({"kategori": svar["kategori"], "adgangsadresseid": svar["resultater"][0]["adresse"]["id"] if ok else None}) unikke = unikke.join(unikke.apply(vask, axis=1)) ids = unikke["adgangsadresseid"].dropna().unique().tolist() punkt = {} for i in range(0, len(ids), 100): bunke = ids[i:i + 100] r = s.get("https://api.danadresse.dk/adgangsadresser", timeout=30, params={ "id": "|".join(bunke), "struktur": "mini", "per_side": len(bunke)}) r.raise_for_status() punkt.update({a["id"]: (a["x"], a["y"]) for a in r.json()}) unikke["x"] = unikke["adgangsadresseid"].map(lambda i: punkt.get(i, (None, None))[0]) unikke["y"] = unikke["adgangsadresseid"].map(lambda i: punkt.get(i, (None, None))[1]) df = df.merge(unikke, on=["vejnavn", "husnr", "postnr"], how="left") df.to_csv("kunder_geokodet.csv", index=False) print(df["kategori"].value_counts())
Læs alle kolonner som tekst (dtype=str). Ellers mister koder med foranstillet nul, som kommunekoden 0101, deres nul, og husnumre som 12A blandes med tal.
Hvilket koordinatsystem?
srid | System | Enhed | Brug |
|---|---|---|---|
4326 (standard) | WGS84 | grader (længde, bredde) | Webkort, GPS, Google Maps, Leaflet |
25832 | ETRS89 / UTM zone 32N | meter (øst, nord) | Afstande, GIS, danske kortdata |
Bemærk rækkefølgen: x er længdegrad og y er breddegrad. Mange værktøjer vil have lat, lon, så byt om, når du skriver til dem. Se Koordinater og srid.
Kanttilfælde
- Ingen koordinater. Nogle få adresser har ikke et adgangspunkt. Så er
xogynull. - Nøjagtighed. Det fulde svar fra
/adgangsadresser/{id}haradgangspunkt.nøjagtighed:Aer målt,Ber beregnet,Uer usikkert. Filtrer på den, hvis præcisionen betyder noget for dig. - Semikolon-filer. Danske Excel-eksporter bruger tit semikolon. Brug
csv.DictReader(f, delimiter=";")ellerpd.read_csv(..., sep=";"). - Allerede kendte id'er. Har du adresse-id'er fra en tidligere vask, så spring datavask over og hent koordinaterne direkte med
GET /adresser?id=a|b|c&struktur=mini.
Næste skridt
- Adresser i en radius eller et polygon
- Rens en CSV-fil fra CRM'et
- Mere om geokodning: geokodning
Relaterede guides
Markdown-kilde Fejl i guiden? Skriv til os API-reference (Swagger)