Cartografie electorală în linie de comandă - Partea 3: Realizarea hărții la nivel de secție de votare (poligon)
3.1. Definirea problemei
Ziceam în introducere că ne-am propus să ilustrăm distribuția votului la cel mai detaliat nivel cu putință. Reprezentările clasice se opresc de regulă la nivel de UAT. Noi avem însă datele la nivel de secție. Este drept, secțiile sînt elemente punctuale și este extrem de greu de definit "bazinul" alocat unei secții. Fiecărei secții îi sînt arondate o serie de adrese iar pe site-ul AEP există o bază de date cu distribuția acestor adrese pe secții. Geocodarea lor și transformarea lor în poligoane este însă o sarcină extrem de dificilă, neștiind ce teritoriu putem aloca pentru fiecare adresă punctuală. De aceea, vom alege o metodă mult mai simplă, chiar dacă nu va produce rezultate precise (de altfel, imposibil de obținut). Pentru acesta am ales să împărțim teritoriul unui UAT în subdiviziuni folosind tehnica poligoanelor Voronoi. Astfel, pentru fiecare secție vom obține un poligon ce are secția în apropiere de centru. Suprafața poligonului va depinde de numărul și de poziția celorlalte secții din cadrul UAT-ului. Cum am precizat deja, nu este suprafața reală a secției de votare dar tehnica ne oferă o metodă decentă de aproximare a acesteia și un bun pretext de spațializare cu o granulometrie mai mare a rezultatelor votului. O potențială problemă o reprezintă secțiile multiple din cadrul unor instituții (cum ar fi școlile). Pentru aceste situații, setul de date cu secții descărcat de la AEP oferă o poziție unică, centrată pe școală sau instituția unde se găsesc secțiile. Am putea "mișca" puțin locațiile acelor secții dar am avea o problemă la generarea poligoanelor Voronoi pentru că ar fi foarte mici. De aceea am luat decizia de a păstra locația unică și de a cumula numărul de voturi la respectivul poligon, păstrînd "istoricul" secțiilor ce au contribuit la rezultat.
Cum procedăm? Deși problema pare simplă, implică un număr important de pași intermediari.
3.2. Spațializarea proceselor verbale
Presupune crearea unor tabele noi, sectii_pv_tur1
în schema tur1
și sectii_pv_tur2
în schema tur2
, care să includă, pe lîngă coloanele cu rezultatele votului, atributele relevante din tabela sectii
:
Rezultatul este prezentat în imaginea de mai jos. Practic, pe lîngă cîmpurile originale din tabela sectii
am adus cîmpurile g[x]
pentru cei 14 candidați din turul 1 și cei 2 candidați din turul 2. Automat, o dată cu acest join, au fost eliminate secțiile din diaspora.

Rezultatul unirii dintre tabela secții și tabelele cu procesele verbale.
3.3. Comasarea secțiilor cu aceeași locație
Spuneam anterior că o serie de secții se găsesc la aceeași adresă, avînd coordonate identice în tabela sectii
. Un exemplu de acest gen este Școala "Sfântu Andrei" din Drumul Taberei unde, pe perioada alegerilor, au funcționat 10 secții de votare:

Exemplu de secții multiple la aceeași adresă.
3.2.1. Ștergerea geometriilor duplicate
Primul pas în vederea comasării este crearea unui strat nou în care secțiile cu geometrie duplicată sînt eliminate. Pentru aceasta facem o copie a tabelei sectii_pv_tur1
pe care o vom denumi sectii_unic
. Apoi vom șterge din această tabelă elementele cu geometrie duplicată:
3.2.2. Crearea de buffer-e pentru secții
În continuare, vom face un buffer de 1 metru în jurul fiecărei secții. Tabela nou creată o vom intitula sectii_buffer
:
3.2.3. Cumularea rezultatelor din secțiile cu geometrie duplicată
Am făcut acest buffer special pentru comasarea secțiilor cu geometrie duplicată. Diametrul mic, de doar 1 metru, ne asigură că nu vom include secții de la altă adresă. Vom folosi funcția SQL SUM
pentru a cumula valorile din cîmpurile g[X]
și pentru a le scrie în două noi tabele intermediare, sectii_buffer_pv_tur1
și sectii_buffer_pv_tur2
. De asemenea, vom folosi funcția STRING_AGG
pentru a stoca în coloana id_sectii
toate indicativele secțiilor ale căror rezultate au fost cumulate. Funcția MAX
nu are decît rolul de a prelua o singură valoare din cîmpurile judet
, uat
, localitate
, institutie
, adresa
și siruta
. Oricum, valorile sînt identice pentru toate secțiile cu valori cumulate.
Figura de mai jos prezintă un exemplu de cumulare a atributelor secțiilor cu geometrii duplicate:

Cumulare a atributelor secțiilor cu geometrii duplicate.
3.2.4. Conversie buffer-e în centroizi
Buffer-ele și-au jucat rolul, e timpul să ne întoarcem la puncte. Pentru aceasta vom converti fiecare buffer în puncte (centroizi), le vom păstra atributele și vom salva tabela nou creată cu numele sectii_pv_cumulat_tur1
, respectiv: sectii_pv_cumulat_tur2
:
3.3. Diverse calcule tabelare
3.3.1. Transferarea voturilor de la secția 8618 la 8606 și de la secția 15499 la 15751
UAT-urile Miercurea Ciuc și Timișoara au insulițe mici în interiorul altor UAT-uri (ex: Aeroportul Internațional Traian Vuia - Timișoara). Deoarece au suprafețe foarte mici, geometriile acestor insulițe au fost șterse în faza de simplificare a limitelor UAT. Pentru a nu pierde voturile, le vom transfera localităților mamă și vom șterge respectivele înregistrări din tabelele sectii_pv_cumulat_tur1
și sectii_pv_cumulat_tur2
.
3.3.2. Calcularea voturilor în procente
Avem numărul de voturi primit de fiecare candidat. Totuși, lumea este obișnuită să analizeze în procente prestația candidaților. Pentru aceasta vom adăuga cîmpuri de tip g[X]p
unde vom introduce procentele obținute de fiecare candidat în fiecare secție:
3.3.3. Calcularea cîștigătorului la nivel de secție
Vom crea o coloană nouă, numită castigator
, în care vom stoca indicativul cîștigătorul respectivei secții. În turul 2, în caz de egaliatate, vom stoca valoarea 0
:
3.4. Crearea poligoanelor asociate secțiilor de votare
3.4.1. Crearea poligoanelor Voronoi
În sfîrșit, am ajuns la pasul în care construim poligoanele secțiilor de votare. După cum am spus mai devreme, facem asta folosind tehnica poligoanelor Voronoi. Ce ne dorim este să construim o interogare care să itereze prin fiecare UAT, să folosească secțiile din respectivul UAT ca informație de intrare pentru funcția ST_VoronoiPolygons
din PostGIS pentru a crea poligoanele asociate fiecărei secții. Evident, deoarece funcția nu are un parametru de "mască" pentru generarea poligoanelor, acestea vor depăși suprafața UAT-ului. De aceea, pentru a decupa poligoanele pe limita UAT-ului, vom folosi funcția ST_Intersection
. Scenariul interogării SQL este prezentat în figura de mai jos:

Etapele generării poligoanelor Voronoi pentru secțiile de votare.
Interogarea se poate scrie după cum urmează:
Secțiile nedecupate arată ca în figura mai jos:

Secțiile nedecupate.
După aplicarea funcției ST_Intersection
lucrurile încep să capete conturul dorit:

Secțiile decupate pe conturile UAT.
Observăm totuși o serie de goluri. Sînt cauzate de UAT-urile unde există o singură secție de votare, algoritmul Voronoi neputînd genera geometrii pe baza unui singur punct.
3.4.2. Utilizarea geometriei UAT-ului acolo unde există o singură secție
Soluția logică în situația UAT-urilor cu o singură secție este utilizarea geometriei UAT-ului pentru reprezentarea secției. Pentru aceasta vom rula următoarele comenzi:
Prima comandă numără iterativ secțiile din fiecare UAT. Atunci cînd totalul este egal cu 1, salvează geometria într-o tabelă nouă, numită gap_voronoi
. Vom obține un număr de 292 de geometrii:

Geometria UAT-urilor cu o singură secție de votare.
A doua comandă comasează poligoanele Voronoi cu geometriile UAT-urilor cu o singură secție, obținînd o hartă cu geometriile tuturor secțiilor de votare din România, salvată în tabela numităST_VoronoiPolygons
:

Geometria secțiilor de votare din România.
În imaginea de mai jos putem observa un detaliu din geometria secțiilor, geometrii peste care am suprapus limitele UAT-urilor și locațiile secțiilor:

Geometria secțiilor de votare din România - detaliu.
3.4.3. Transferul atributelor de la stațiile de tip punct către poligoanele Voronoi
Operațiile desfășurate anterior s-au făcut doar la nivel de geometrii. Este necesar să asociem și atributele calculate deja la nivel de secție de tip punct cu noile poligoane. Pentru aceasta vom folosi funcția PostGIS ST_Within:
Avînd rezultatele votului asociat cu geometriile poligonale ale secțiilor, putem face o primă încercare de a da culoare votului:

Simbolizarea secțiilor în funcție de cîștigătorul din primul tur.
3.4.4. Inserarea unei entități pentru reprezentarea voturilor din diaspora
BEC publică rezultatele pentru diaspora într-o manieră similară. Scopul nostru este de a prezenta rezultatele la nivel național dar vom include o geometrie separată pentru a centraliza rezultatele din diaspora. Numărul de voturi pentru candidații din cele două tururi a fost preluat de pe platforma informatică a BEC. Noul element vectorual va primi codul gid
: 20000
.
Rezultatul este prezentat în figura mai jos:

Inserarea unei entități pentru reprezentarea voturilor din diaspora.
3.5. Ștergerea tabelelor temporare
Pe măsură ce lucrăm, în schema sandbox
, se acumulează seturi relativ mari cu rezultate intermediare, date de care nu mai avem nevoie o dată cu obținerea tabelului final. Vom șterge respectivele tabele pentru a nu încărca discul mașinii virtuale cu date nefolositoare:
3.6. Concluzii de etapă
În cele scrise pînă acum, am arătat cum datele deschise, disponibile online, pot fi utilizate pentru a spațializa rezultatele alegerilor prezidențiale la nivel de secție de votare. E drept, limita secțiilor este una fictivă dar care ne ajută să "vedem" mai bine cum arată harta politică a alegerilor prezidențiale din 2019 în România. În continuare, vom vedea dacă se poate coborî mai jos de nivelul de secție, precum și cum putem automatiza procesul de creare a hărților la nivele ceva mai convenționale (UAT, județ).