Tutorial 6: References¶
In this tutorial we will learn how to re-use data from other nodes using references.
Spain - General elections - Parliament - Full process¶
The elections for the National Parliament requires two steps:
Distribution of seats among districts (see Spain - National Parliament - Districts apportionment)
Seats allocation among candidates (see Spain - Andalusian regional election)
Now we will compose the full schema:
We now have to sets of votes:
census aggregated by province
election vote to party lists
Census aggregated by province: we just need to copy the schema from the previous tutorial (Spain - National Parliament - Districts apportionment) and make some adjustments:
1name: Elecciones a Cortes Generales 2type: group 3divisions: 4 5- name: Distribución de escaños 6 type: group 7 aggregate: yes 8 meta: 9 notes: | 10 Seats apportionment based on provintial census 11 divisions: 12 - name: Ciudades autónomas 13 method: noop 14 initial_seats: 1 15 - name: Provincias 16 seats: 248 17 method: largest_remainder 18 method_params: 19 quota_f: hare 20 initial_seats: 2 21 resume_allocation: no
In line 7 we enable the generation of a result, so that we can have a flattened list for both autonomous cities and provinces.
In line 8-9, a comment was added. Custom properties can be added to a district using the
metacontainer.Election vote to party lists: a schema similar to the one we used for Spain - Andalusian regional election will be addded, but we will use references to the seats computed by the node
Distribución de escaños:1name: Elecciones a Cortes Generales 2type: group 3divisions: 4 5- name: Distribución de escaños 6 type: group 7 aggregate: yes 8 meta: 9 notes: | 10 Seats apportionment based on provintial census 11 divisions: 12 - name: Ciudades autónomas 13 method: noop 14 initial_seats: 1 15 - name: Provincias 16 seats: 248 17 method: largest_remainder 18 method_params: 19 quota_f: hare 20 initial_seats: 2 21 22- name: Circunscripciones 23 type: group 24 aggregate: yes 25 method: highest_averages 26 method_params: 27 divisor_f: dhondt 28 exclude: valid_votes < 3% 29 meta: 30 notes: | 31 Seats allocation based on votes 32 divisions: 33 - name: Andalucía 34 type: group 35 aggregate: yes 36 divisions: 37 - name: Almería 38 seats: Distribución de escaños 39 - name: Cádiz 40 seats: Distribución de escaños 41 - name: Córdoba 42 seats: Distribución de escaños 43 - name: Granada 44 seats: Distribución de escaños 45 - name: Huelva 46 seats: Distribución de escaños 47 - name: Jaén 48 seats: Distribución de escaños 49 - name: Málaga 50 seats: Distribución de escaños 51 - name: Sevilla 52 seats: Distribución de escaños 53 ... 54 - name: País Vasco 55 type: group 56 aggregate: yes 57 divisions: 58 - name: Araba/Álava 59 seats: Distribución de escaños 60 - name: Bizkaia 61 seats: Distribución de escaños 62 - name: Gipuzkoa 63 seats: Distribución de escaños
There are two differences from the old version:
An intermediate group level was added in order to get results aggregated by autonomous regions.
The seats for provinces are no longed hard-coded. Now they are using the values computed by the node
Distribución de escaños. If a candidate with the same name as the district who references is found, the computed seats will be used.
Zurich - Bi-proportional system¶
We will use more references defining a new kind of method, the bi-proportional allocation ([Zachariasen:2006], [Pukelsheim:2013], [Oelbermann:2016])
In 2006, the Canton of Zürich 125 seats were allocated among 9 districts keeping two proportionalities:
The number of seats assigned to districts is proportional.
The number of seats assigned to parties is also proportional.
Seats are assigned to parties in district keeping the restrictions above.
In the first step party seats and district seats are computed for the whole Canton. Then, seats are reapportioned to parties in districts in a single allocation process using the Sainte-Laguë divisor method.
1name: Zürich Canton Parliament 2006
2type: group
3divisions:
4- name: biproportional
5 method: alternate_scaling
6 method_params:
7 round_f: sainte_lague
8 nice_quota: yes
9 sort_parties: yes
10 candidates: Wahlkreise
11 party_seats:
12 name: party seats
13 method: highest_averages
14 method_params:
15 divisor_f: sainte_lague
16 seats: 125
17 candidates: id[Wahlkreise]
18 district_seats:
19 method: noop
20 candidates:
21 - {name: "WK1+2", min_seats: 12}
22 - {name: "WK3", min_seats: 16}
23 - {name: "WK4+5", min_seats: 13}
24 - {name: "WK6", min_seats: 10}
25 - {name: "WK7+8", min_seats: 17}
26 - {name: "WK9", min_seats: 16}
27 - {name: "WK10", min_seats: 12}
28 - {name: "WK11", min_seats: 19}
29 - {name: "WK12", min_seats: 10}
30
31- name: Wahlkreise
32 method: noop
33 candidates:
34 - { district: WK1+2, name: SP, votes: 28518 }
35 - { district: WK1+2, name: SVP, votes: 15305 }
36 - { district: WK1+2, name: FDP, votes: 21833 }
37 - { district: WK1+2, name: Grüne, votes: 12401 }
38 - { district: WK1+2, name: CVP, votes: 7318 }
39 - { district: WK1+2, name: EVP, votes: 2829 }
40 - { district: WK1+2, name: AL, votes: 2413 }
41 - { district: WK1+2, name: SD, votes: 1651 }
42
43 ...
44
45 - { district: WK12, name: SP, votes: 13215 }
46 - { district: WK12, name: SVP, votes: 10248 }
47 - { district: WK12, name: FDP, votes: 3066 }
48 - { district: WK12, name: Grüne, votes: 2187 }
49 - { district: WK12, name: CVP, votes: 4941 }
50 - { district: WK12, name: EVP, votes: 0 }
51 - { district: WK12, name: AL, votes: 429 }
52 - { district: WK12, name: SD, votes: 2078 }
Create the electoral districts:
31- name: Wahlkreise 32 method: noop 33 candidates: 34 - { district: WK1+2, name: SP, votes: 28518 } 35 - { district: WK1+2, name: SVP, votes: 15305 } 36 - { district: WK1+2, name: FDP, votes: 21833 } 37 - { district: WK1+2, name: Grüne, votes: 12401 } 38 - { district: WK1+2, name: CVP, votes: 7318 } 39 - { district: WK1+2, name: EVP, votes: 2829 } 40 - { district: WK1+2, name: AL, votes: 2413 } 41 - { district: WK1+2, name: SD, votes: 1651 } 42 43 ... 44 45 - { district: WK12, name: SP, votes: 13215 } 46 - { district: WK12, name: SVP, votes: 10248 } 47 - { district: WK12, name: FDP, votes: 3066 } 48 - { district: WK12, name: Grüne, votes: 2187 } 49 - { district: WK12, name: CVP, votes: 4941 } 50 - { district: WK12, name: EVP, votes: 0 } 51 - { district: WK12, name: AL, votes: 429 } 52 - { district: WK12, name: SD, votes: 2078 }
This node will be a simple container, with no allocation per se. Note that the field
districtis specified explicitly for contenders. This is the equivalent of this hierarchical schema:31- name: Wahlkreise 32 type: group 33 method: noop 34 divisions: 35 - name: WK1+2 36 candidates: 37 - { name: SP, votes: 28518 } 38 - { name: SVP, votes: 15305 } 39 - { name: FDP, votes: 21833 } 40 - { name: Grüne, votes: 12401 } 41 - { name: CVP, votes: 7318 } 42 - { name: EVP, votes: 2829 } 43 - { name: AL, votes: 2413 } 44 - { name: SD, votes: 1651 } 45 46 ... 47 48 - name: WK12 49 candidates: 50 - { name: SP, votes: 13215 } 51 - { name: SVP, votes: 10248 } 52 - { name: FDP, votes: 3066 } 53 - { name: Grüne, votes: 2187 } 54 - { name: CVP, votes: 4941 } 55 - { name: EVP, votes: 0 } 56 - { name: AL, votes: 429 } 57 - { name: SD, votes: 2078 }
Create a node for district seats. This is not computed here:
18district_seats: 19 method: noop 20 candidates: 21 - {name: "WK1+2", min_seats: 12} 22 - {name: "WK3", min_seats: 16} 23 - {name: "WK4+5", min_seats: 13} 24 - {name: "WK6", min_seats: 10} 25 - {name: "WK7+8", min_seats: 17} 26 - {name: "WK9", min_seats: 16} 27 - {name: "WK10", min_seats: 12} 28 - {name: "WK11", min_seats: 19} 29 - {name: "WK12", min_seats: 10}
Seats are set using
min_seats.
Allocate seats to parties:
11party_seats: 12 name: party seats 13 method: highest_averages 14 method_params: 15 divisor_f: sainte_lague 16 seats: 125 17 candidates: id[Wahlkreise]
Note that instead of giving a list of candidates, a reference is used:
id[Wahlkreise]. This will get the Wahlkreise node’s candidates and will apply a transformation byid(it will remove districts).
Allocate bi-proportionally:
4- name: biproportional 5 method: alternate_scaling 6 method_params: 7 round_f: sainte_lague 8 nice_quota: yes 9 sort_parties: yes 10 candidates: Wahlkreise 11 party_seats: 12 ... 13 district_seats: 14 ...
It will use the
alternate scalingmethod, and the candidates will be retrieved from Wahlkreise again, but no transformations are made (name, alliance and district is preserved).