Genereren PC6 vlakken

Toevallig kwam dit vandaag weer eens op mijn pad. Via een PDOK-afnemer die problemen ondervond, mogelijk veroorzaakt door artefacten van bovengenoemde generalisatie. De auteurs in deze topic hebben duidelijk veel kennis over deze materie.

Ik weet er ook wel wat van, m.n. dat het geen exacte wetenschap is, meer dan een beetje ‘Voronoi’ . @raymondnijssen bood ooit een PC6 vlakken product aan. Maar in alle gevallen is dus de broncode, ook van ESRI neem ik aan, niet Open Source. Dat is ergens bizar, er wordt vaak geroepen om “authentieke gegevens”.

Dus: waarom niet bijvoorbeeld een subproject op NLExtract? Vanuit BAG v2 naar PostGIS worden allerlei nieuwe datasets afgeleid zoals adressen CSVs. Maar mag ook een PDOK open source project zijn. Transparantie, samen weten/kunnen we meer!

Er zit wel verschil tussen het openbaar maken van de ontwerpkeuzes (“open source knowledge”), waar @JBak er een aantal van noemt, en het implementeren van die ontwerpkeuzes (in hetzij open source , hetzij niet-open source software).

NLExtract bestrijkt volgens mij allebei die delen (ontwerp én implementatie), maar het lijkt me niet reeël, zelfs bijna onzinnig, om van Esri-Nederland te verwachten dat zij hun implementatie met andere tooling dan ArcGIS zouden doen.

Ben uiteraard zeer benieuwd hoe Esri-NL, PDOK, CBS en anderen (NDW? Kadaster?) aankijken tegen zo’n vorm van kennisdelen.

Nb. dit topic gaat een andere kant uit dan “update voor CBS PC4 en PC6”.
Kun je op dit Geoforum een thread afsplitsen onder een nieuwe titel?

Precies zoals je schrijft. Wij delen de ontwerpkeuzes open, kan iedereen daarna zelf kiezen hoe je die zo handig mogelijk implementeert in de technologie naar keuze en eventueel verrijkt of andere keuzes maakt. #keuzevrijheid

Wij implementeren die op onze beurt dan in ArcGIS, met een combinatie van standaardtools en her en der wat python. En het resultaat delen we vervolgens ook nog eens onder een open data licentie. Wij maken het voor ons klanten, en stellen het aan die groep beschikbaar. Distributie breder doen we niet zelf, maar loopt via CBS/PDOK, als geometrie bij de Postcode4 en Postcode 6 data - waar het in de kern in dit topic om gaat.

Kennisdelen is voor veel meer mogelijk, bijvoorbeeld ook hoe we woningtypering dataset maken (hoekwoning, appartement, vrijstaand huis etc).

Hoi, de SQL voor berekenen van pc6 (en afgeleide pc5, 4, 3, 2, 1) op basis van de BAG uit NL-extract staat hier:

1 like

Dank voor de antwoorden en @raymondnijssen voor script. Ik ga volgende week met de set aan de slag, sowieso om te kijken of de huidige problemen daarmee door de generalisatie worden veroorzaakt.

Ik verwacht niet van ESRI dat ze iets gaan OpenSourcen. Dacht dat ze daar misschien ook gewoon PostGIS SQL zouden gebruiken. Maar ik ken de producten niet…Hoopte natuurlijk stiekem dat iemand direct aan NLExtract zou bijdragen…En dus… denk dat we met het raymondnijssen script, een mooi begin hebben!

Was ook al oud topic, wordt mogelijk vervolgd als er dus problemen met de huidige set zijn.

Dankjewel, gedaan!

@JBak Heb je misschien een link naar jullie ontwerpkeuzes? Ben ik wel benieuwd naar :slightly_smiling_face:.
Met het script van @raymondnijssen kom ik een heel eind in DuckDB, zij het met buurtgrenzen ipv woonplaats (die dekken niet heel NL af, dus dan verlies je wat postcodes). Maar ik vermoed dat er ook nog wel andere grenzen worden gebruikt zoals (spoor)wegen enz om het wat strakker te krijgen als ik naar verschillen kijk met jullie viewer?

Wat ik nu heb weten te maken is hier te vinden (pc6.gpkg).

Je kan hier eens starten, in de online productdocumentatie: Postcodevlakken. En dan specifiek onder “ontwerpkeuzes”. Daar staan nu niet alle keuzes beschreven, maar wel wat essentiele qua 1e voorbereidingsstap om de BAG data geschikt te maken voor het maken van postcodevlakken (conform onze uitgangspunten…). Het is namelijk best interessant om te zien wat voor situaties er zijn met adressen op dezelfde X,Y maar met verschillende postcodes en nog wat variaties daarop. In essentie begint de productie bij ons met eerst de BAG data wat opschonen/voorbereiden, op basis van de bijzondere situaties die voorkomen. Pas zodra dat is gedaan (en dat doen we met een python script overigens) - wordt gestart met het maken van de vlakken zelf. En daarin worden diverse grensbestanden gebruikt als barriers (eerst harde barrieres, later zachte barrieres), waarbij spoorwegen inderdaad één van de bronnen is. Als er interesse is in alle bronnen die gebruikt worden, laat maar weten. Vraag ik het team daar even uitdraai van te maken.

2 likes

Leuk dat je een heel eind gekomen bent! De queries zijn geschreven voor PostreSQL dus ik kan me voorstellen dat DuckDB (nog) niet alles ondersteund. Ben wel benieuwd hoe ver je kwam en hoe snel het gaat. De doorlooptijden op mijn (oude) laptop heb ik in het commentaar gezet.

En ik weet dat de BAG-woonplaatsen slecht aansluiten maar dat gaat toch over millimeters? Vallen er echt adressen in die strookjes? Ik heb dat nooit getest.

Bij het gebruik van de buurtkaart krijg je weer extra grenzen tussen postcodes terwijl die er in werkelijkheid niet zijn. Net als bij het gebruik van wegen. Maar dat zijn natuurlijk ontwerpkeuzes en het hangt van je doel af wat je er mee kunt.

Zelf gebruik ik tegenwoordig meestal een de een postcode puntenkaart waar ik de gemiddelde x en gemiddelde y van alle AOB’s met dezelfde postcode bereken. Dat is simpel en super snel, en voorkomt ook het vertekende kaartbeeld met enorme gekleurde vlakken in het buitengebied terwijl daar haast geen data is. (Ja ik weet het, dat moet je normaliseren met de oppervlakte of aantal adressen maar dat doet helaas bijna niemand.)

Wat DuckDB niet ondersteunt is bijvoorbeeld een boundary geometry bij het creëren van een Voronoi diagram, dus dat moet dan in een aparte stap worden geclipt met een ST_Intersection. Dat doe ik nu dus aan de hand van buurten. Daar waar een postcode zo’n grens overgaat lijkt dat niet veel uit te maken, die sluiten dan wel weer aan (wellicht wat hoekiger); maar er zijn sowieso ook al zat postcodegebieden die niet aansluiten.

Bij woonplaatsen mis ik echt een paar best grote vlakken, het zijn geen randgevallen. Daar nu naar kijkend denk ik dat dit een fout is in mijn code bij het inlezen van de BAG. Het lijken allemaal woonplaatsen met disjuncte oppervlakten (Elim, Blauwestad, Noordseschut, Leerbroek, Geldermalsen, maar ook Amsterdam), dat zal helpen bij het zoeken van de oorzaak :grin:. Toch nuttig zo’n compleet ongerelateerde zoektocht :wink:.

Totale tijd van alle stappen (op mijn meer dan 6 jaar oude Ryzen 5 2600) is onder de 2,5 minuut. Zie beneden voor de SQL met timings.

De beschrijving van @JBak (dank!) geeft richting en kan ik mooi mee verder knutselen, dat is toch het leukst.

DuckDB SQL voor genereren postcode6
-- 17s
-- Determine all unique locations
-- Assign most common postcode at overlaps
CREATE OR REPLACE TABLE pc_loc AS
SELECT
  bu_code,
  min(postcode) AS min_pc,
  list_mode(list_sort(list(postcode))) as mode_pc,
  list_sort(list(DISTINCT postcode)) AS all_pc,
  count(*) AS adr_cnt,
  loc AS loc
FROM addresses
WHERE postcode is not NULL
GROUP BY bu_code, loc;

-- 10s
-- create voronoi diagram and unnest tiles
create or replace table pc_vor as select
	bu_code, 
	unnest(ST_Dump(ST_VoronoiDiagram(ST_Collect(list(loc))))).geom as geom
from pc_loc 
group by bu_code;

-- 37s
-- clip tiles to buurt since DuckDB does not
-- support providing outer geom for ST_VoronoiDiagram
create or replace table pc_vor1 as select 
	v.bu_code, 
	st_intersection(v.geom, bu.geom) as geom 
from pc_vor v left join buurt bu on v.bu_code=bu.bu_code;

-- 12s
-- Combine tiles with locations
-- appr. 1800 locations will have no geom!
-- (at the edge of gemeente, e.g. near coast/water)
create or replace table pc_com as select 
	v.bu_code, 
	v.geom, 
	l.loc, 
	l.min_pc,
	l.mode_pc, 
	l.adr_cnt 
from pc_loc l left join pc_vor1 v on ST_Within(l.loc, v.geom);

-- 1m5s
-- combine all tiles with the same postcode
-- and count the number of separate geometries
CREATE OR REPLACE TABLE pc6 AS
SELECT
  mode_pc as postcode6,
  sum(adr_cnt)::INTEGER AS address_count,
  ST_NGeometries(ST_Union_Agg(geom)) AS parts,
  ST_Union_Agg(geom) AS geom
FROM pc_com 
GROUP BY all;

2 likes

Ik heb een lange tijd geleden een (vrij simpele) QGIS model gemaakt om PC4- en PC6-vlakken te maken, gebaseerd op gegevens uit de BAG (VBO’s).
Als je geïnteresseerd bent, stuur gerust dan een bericht naar mij.