Updaters and Elections

Updaters

class gerrychain.updaters.CountySplit(value)[source]

Enum to track county splits in a partition.

NOT_SPLIT

The county is not split.

Type:

CountySplit

NEW_SPLIT

The county became split after the initial partition.

Type:

CountySplit

OLD_SPLIT

The county has remained split since the initial partition.

Type:

CountySplit

class gerrychain.updaters.DataTally(data: Mapping[Hashable, float] | Sequence[float] | Series | str, alias: str)[source]

An updater for tallying numerical data that is not necessarily stored as node attributes

data

A Dict or Series indexed by the graph’s nodes, or the string key for a node attribute containing the Tally’s data.

Type:

dict | pandas.Series | str

alias

The name of the tally in the Partition’s updaters dictionary

Type:

str

Initialize a DataTally instance.

Parameters:
  • data (dict | Sequence | pandas.Series | str) – A Dict, Series, or sequence indexed by the graph’s nodes, or the string key for a node attribute containing the Tally’s data.

  • alias (str) – The name of the tally in the Partition’s updaters dictionary

class gerrychain.updaters.Election(name: str, party_names_to_node_attribute_names: Mapping[str, str | Sequence[float]] | list[str], alias: str | None = None)[source]

Represents the data of one election, with races conducted in each part of the partition.

As we vary the districting plan, we can use the same node-level vote totals to tabulate hypothetical elections. To do this manually with tallies, we would have to maintain tallies for each party, as well as the total number of votes, and then compute the electoral results and percentages from scratch every time. To make this simpler, this class provides an ElectionUpdater to manage these tallies. The updater returns an ElectionResults class giving a convenient view of the election results, with methods like ElectionResults.wins or ElectionResults.percent for common queries the user might make on election results.

Example usage:

# Assuming your nodes have attributes "2008_D", "2008_R"
# with (for example) 2008 senate election vote totals
election = Election(
    "2008 Senate",
    {"Democratic": "2008_D", "Republican": "2008_R"},
    alias="2008_Sen"
)

# Assuming you already have a graph and assignment:
partition = Partition(
    graph,
    assignment,
    updaters={"2008_Sen": election}
)

# The updater returns an ElectionResults instance, which
# we can use (for example) to see how many seats a given
# party would win in this partition using this election's
# vote distribution:
partition["2008_Sen"].wins("Republican")
name

The name of the election. (e.g. “2008 Presidential”)

Type:

str

parties

A list of the names of the parties in the election.

Type:

list[str]

node_attribute_names

A list of the node_attribute_names in the graph’s node

Type:

list[str]

data that

hold the vote totals for each party.

party_names_to_node_attribute_names

A dictionary mapping party names to

Type:

dict[str, str]

the

node_attribute_names in the graph’s node data that hold the vote totals for that party.

tallies

A dictionary mapping party names to DataTally

Type:

dict[str, DataTally]

objects

that manage the vote totals for that party.

updater

An ElectionUpdater object that manages the tallies and returns an ElectionResults object.

Type:

ElectionUpdater

alias

The name that the election is registered under in the partition’s dictionary of updaters.

Type:

str

Initialize a Election instance.

Parameters:
  • name (str) – The name of the election. (e.g. “2008 Presidential”)

  • party_names_to_node_attribute_names (dict | list) –

    A mapping from the name of a party to the name of an attribute of a node that contains the vote totals for that party. This parameter can be either a list or a dict. If a list, then the name of the party and the name of the node attribute are the same, for instance: [“Dem”, “Rep”] would indicate that the “Dem” party vote totals are stored in the “Dem” node attribute. If a list, then there are two possibilities.

    A dictionary matching party names to their data node_attribute_names, either as actual node_attribute_names (list-like, indexed by nodes) or as string keys for the node attributes that hold the party’s vote totals. Or, a list of strings which will serve as both the party names and the node attribute keys.

  • alias (str | None, optional) – Alias that the election is registered under in the Partition’s dictionary of updaters. Defaults to None, which uses name.

class gerrychain.updaters.Tally(fields: str | list[str], alias: str | None = None, dtype_fn: ~collections.abc.Callable[[], float] = <class 'int'>)[source]

An updater for keeping a tally of one or more node attributes.

fields

The list of node attributes that you want to tally. Or just

Type:

str | list[str]

a

single attribute name as a string.

alias

The aliased name of this Tally (meaning, the key corresponding to this Tally in the Partition’s updaters dictionary)

Type:

str | None

dtype_fn

A zero-argument callable that creates the tally’s initial value.

Type:

Callable[[], float]

Initialize a Tally instance.

Parameters:
  • fields (str | list[str]) – The list of node attributes that you want to tally. Or a just a single attribute name as a string.

  • alias (str | None, optional) – The aliased name of this Tally (meaning, the key corresponding to this Tally in the Partition’s updaters dictionary). Default is None.

  • dtype_fn (Callable[[], float], optional) – A zero-argument callable that creates the tally’s initial value. Defaults to int.

gerrychain.updaters.boundary_nodes(partition: Partition, alias: str = 'boundary_nodes') set[Hashable][source]

Return set of nodes in the partition that are on the boundary.

Parameters:
  • partition (Partition) – A partition of a Graph

  • alias (str, optional) – The name of the attribute that the boundary nodes are stored under. Default is ‘boundary_nodes’.

Returns:

The set of nodes in the partition that are on the boundary.

Return type:

set

gerrychain.updaters.compute_edge_flows(partition: Partition) dict[Hashable, dict[str, set[tuple[int, int]]]][source]

Computes the flow of cut edges between a partition and its parent.

Parameters:

partition (Partition) – A partition of a Graph

Returns:

A flow dictionary containing the flow from the parent of this partition to this

partition. This dictionary is of the form {part: {‘in’: <set of edges that flowed in>, ‘out’: <set of edges that flowed out>}}.

Return type:

dict

gerrychain.updaters.county_splits(partition_name: str, county_field_name: str) Callable[[Partition], dict[Hashable, CountyInfo]][source]

An updater for tracking the number of counties that are split in a partition.

Parameters:
  • partition_name (str) – Name that the Partition instance will store.

  • county_field_name (str) – Name of county ID field on the graph.

Returns:

The tracked data is a dict[Hashable, CountyInfo] keyed on the county ID. Each

CountyInfo is a named tuple with fields split (a CountySplit enum), nodes (a list of node IDs in the county), and contains (a set[Hashable] of the assignment IDs the county intersects).

Return type:

Callable

gerrychain.updaters.cut_edges(partition: Partition) set[tuple[int, int]][source]

Computes the set of edges for a given partition.

Parameters:

partition (Partition) – A partition of a Graph

Returns:

The set of edges that are cut by the given partition.

Return type:

set[tuple]

gerrychain.updaters.cut_edges_by_part(partition: Partition, previous: set[tuple[int, int]], new_edges: set[tuple[int, int]], old_edges: set[tuple[int, int]]) set[tuple[int, int]][source]

Updater that returns a dictionary mapping each part of a partition to the set of cut edges in that part.

Parameters:
  • partition (Partition) – A partition of a Graph

  • previous (set[tuple]) – The previous set of edges for a fixed part of the given partition.

  • new_edges (set[tuple]) – The set of edges that have flowed into the given part of the partition.

  • old_edges (set[tuple]) – The set of cut edges in the previous partition.

Returns:

The new set of cut edges for the newly generated partition.

Return type:

set

gerrychain.updaters.exterior_boundaries(partition: Partition, previous: float, inflow: set[Hashable], outflow: set[Hashable]) float[source]

Computes the total perimeter of the boundary nodes in each part of the partition.

Parameters:
  • partition (Partition) – A partition of a Graph

  • previous (float) – Previous exterior boundary perimeter for the part.

  • inflow (set[Hashable]) – Nodes that flowed into the part.

  • outflow (set[Hashable]) – Nodes that flowed out of the part.

Returns:

The updated exterior boundary perimeter for the part.

Return type:

float

gerrychain.updaters.exterior_boundaries_as_a_set(partition: Partition, previous: set[Hashable], inflow: set[Hashable], outflow: set[Hashable]) set[Hashable][source]

Updater function that responds to the flow of nodes between different partitions.

Parameters:
  • partition (Partition) – A partition of a Graph

  • previous (set[Hashable]) – Previous exterior boundary nodes for a fixed part.

  • inflow (set[Hashable]) – Nodes that flowed into the part.

  • outflow (set[Hashable]) – Nodes that flowed out of the part.

Returns:

The updated exterior boundary nodes for the part.

Return type:

set[Hashable]

gerrychain.updaters.flips(partition: Any) Any

Compatibility updater returning Partition.flips.

Parameters:

partition (Any) – Partition whose flips should be returned.

Returns:

The partition’s flips mapping, or None when it has no flips.

Return type:

Any

gerrychain.updaters.flows_from_changes(old_partition: Partition, new_partition: Partition) dict[Hashable, dict[str, set[Hashable]]][source]

Return per-part node flow updates between two partitions.

Parameters:
  • old_partition (Partition) – A partition of a Graph representing the previous step.

  • new_partition (Partition) – A partition of a Graph representing the current step.

Returns:

A dictionary mapping each node that changed assignment between the previous and

current partitions to a dictionary of the form {‘in’: <set of nodes that flowed in>, ‘out’: <set of nodes that flowed out>}.

Return type:

dict

gerrychain.updaters.interior_boundaries(partition: Partition, previous: float, new_edges: set[tuple[int, int]], old_edges: set[tuple[int, int]]) float[source]

Computes the total perimeter of the shared boundary between different parts of the partition.

Parameters:
  • partition (Partition) – A partition of a Graph

  • previous (float) – Previous interior boundary perimeter for the part.

  • new_edges (set[tuple[int, int]]) – Edges that flowed into the part.

  • old_edges (set[tuple[int, int]]) – Edges that flowed out of the part.

Returns:

The updated interior boundary perimeter for the part.

Return type:

float

gerrychain.updaters.num_spanning_trees(partition: Partition) dict[Hashable, int][source]

Return number of spanning trees in each part (district) of a partition.

Returns:

The number of spanning trees in each part of a partition.

Return type:

dict[Hashable, int]

gerrychain.updaters.perimeter(partition: Partition) dict[Hashable, float][source]

Computes the perimeter of each part in the partition.

Parameters:

partition (Partition) – A partition of a Graph

Returns:

Parts mapped to their perimeter.

Return type:

dict[Hashable, float]

gerrychain.updaters.tally_region_splits(region_attr_lst: Sequence[str]) Callable[[Partition], dict[str, int]][source]

A naive updater for tallying the number of times a region attribute is split.

Here “region” is the generic term for an administrative unit you would prefer not to split (e.g. a county, municipality, or other locality). Each entry in region_attr_lst is the name of a node attribute holding the region label; the county and locality updaters are just specific instances of this region concept.

Parameters:

region_attr_lst (Sequence[str]) – Region attribute names to tally splits for.

Returns:

A function that takes a partition and returns a dictionary which maps the region

name to the number of times that it is split in a a particular partition.

Return type:

Callable

Elections

class gerrychain.updaters.election.Election(name: str, party_names_to_node_attribute_names: Mapping[str, str | Sequence[float]] | list[str], alias: str | None = None)[source]

Represents the data of one election, with races conducted in each part of the partition.

As we vary the districting plan, we can use the same node-level vote totals to tabulate hypothetical elections. To do this manually with tallies, we would have to maintain tallies for each party, as well as the total number of votes, and then compute the electoral results and percentages from scratch every time. To make this simpler, this class provides an ElectionUpdater to manage these tallies. The updater returns an ElectionResults class giving a convenient view of the election results, with methods like ElectionResults.wins or ElectionResults.percent for common queries the user might make on election results.

Example usage:

# Assuming your nodes have attributes "2008_D", "2008_R"
# with (for example) 2008 senate election vote totals
election = Election(
    "2008 Senate",
    {"Democratic": "2008_D", "Republican": "2008_R"},
    alias="2008_Sen"
)

# Assuming you already have a graph and assignment:
partition = Partition(
    graph,
    assignment,
    updaters={"2008_Sen": election}
)

# The updater returns an ElectionResults instance, which
# we can use (for example) to see how many seats a given
# party would win in this partition using this election's
# vote distribution:
partition["2008_Sen"].wins("Republican")
name

The name of the election. (e.g. “2008 Presidential”)

Type:

str

parties

A list of the names of the parties in the election.

Type:

list[str]

node_attribute_names

A list of the node_attribute_names in the graph’s node

Type:

list[str]

data that

hold the vote totals for each party.

party_names_to_node_attribute_names

A dictionary mapping party names to

Type:

dict[str, str]

the

node_attribute_names in the graph’s node data that hold the vote totals for that party.

tallies

A dictionary mapping party names to DataTally

Type:

dict[str, DataTally]

objects

that manage the vote totals for that party.

updater

An ElectionUpdater object that manages the tallies and returns an ElectionResults object.

Type:

ElectionUpdater

alias

The name that the election is registered under in the partition’s dictionary of updaters.

Type:

str

Initialize a Election instance.

Parameters:
  • name (str) – The name of the election. (e.g. “2008 Presidential”)

  • party_names_to_node_attribute_names (dict | list) –

    A mapping from the name of a party to the name of an attribute of a node that contains the vote totals for that party. This parameter can be either a list or a dict. If a list, then the name of the party and the name of the node attribute are the same, for instance: [“Dem”, “Rep”] would indicate that the “Dem” party vote totals are stored in the “Dem” node attribute. If a list, then there are two possibilities.

    A dictionary matching party names to their data node_attribute_names, either as actual node_attribute_names (list-like, indexed by nodes) or as string keys for the node attributes that hold the party’s vote totals. Or, a list of strings which will serve as both the party names and the node attribute keys.

  • alias (str | None, optional) – Alias that the election is registered under in the Partition’s dictionary of updaters. Defaults to None, which uses name.

class gerrychain.updaters.election.ElectionResults(election: Election, counts: dict[str, dict[Hashable, float]], regions: Iterable[Hashable])[source]

Represents the results of an election. Provides helpful methods to answer common questions you might have about an election (Who won? How many seats?, etc.).

election

The Election object that these results are associated with.

Type:

Election

totals_for_party

Party names mapped to their vote totals in each part.

Type:

dict[str, dict[Hashable, float]]

regions

Regions included in the results.

Type:

tuple[Hashable, …]

totals

Parts mapped to their total votes.

Type:

dict[Hashable, float]

percents_for_party

Party names mapped to their vote percentages in each part.

Type:

dict[str, dict[Hashable, float]]

Note

The variable “regions” is generally called “parts” in other sections of the codebase, but we have changed it here to avoid confusion with the parameter “party” that often appears within the class.

Initialize a ElectionResults instance.

Parameters:
  • election (Election) – The Election object that these results are associated with.

  • counts (dict[str, dict[Hashable, float]]) – Party names mapped to the total number of votes that party received in each part of the partition.

  • regions (Iterable[Hashable]) – Regions to consider, such as congressional districts.

count(party: str, region: Hashable | None = None) float[source]

Return vote total for party in one region or overall.

If region is provided, this returns the total vote count in that region. Otherwise, it returns the overall vote total of party across all regions.

Parameters:
  • party (str) – Party ID.

  • region (Hashable | None, optional) – ID of the part of the partition whose votes we want to tally.

Returns:

The total number of votes that party received in a given region (part of the

partition). If region is omitted, returns the overall vote total of party.

Return type:

float

counts(party: str) tuple[float, ...][source]

Return tuple of the total votes cast for party in each part of the partition.

Parameters:

party (str) – Party ID

Returns:

tuple of the total votes cast for party in each part of the partition

Return type:

tuple

efficiency_gap() float[source]

Computes the efficiency gap for this ElectionResults object.

See: gerrychain.metrics.partisan.efficiency_gap

Returns:

The efficiency gap for this election.

Return type:

float

mean_median() float[source]

Computes the mean-median score for this ElectionResults object.

See: gerrychain.metrics.partisan.mean_median

Returns:

The mean-median score for this election.

Return type:

float

mean_thirdian() float[source]

Computes the mean-thirdian score for this ElectionResults object.

See: gerrychain.metrics.partisan.mean_thirdian

Returns:

The mean-thirdian score for this election.

Return type:

float

partisan_bias() float[source]

Computes the partisan bias for this ElectionResults object.

See: gerrychain.metrics.partisan.partisan_bias

Returns:

The partisan bias for this election.

Return type:

float

partisan_gini() float[source]

Computes the Gini score for this ElectionResults object.

See: gerrychain.metrics.partisan.partisan_gini

Returns:

The partisan Gini score for this election.

Return type:

float

percent(party: str, region: Hashable | None = None) float[source]

Return vote share for party in one region or overall.

If region is provided, this returns the vote share in that region. Otherwise, it returns the overall vote share of party across all regions.

Parameters:
  • party (str) – Party ID.

  • region (Hashable | None, optional) – ID of the part of the partition whose votes we want to tally.

Returns:

The percentage of the vote that party received in a given region (part of

the partition). If region is omitted, returns the overall vote share of party.

Return type:

float

percents(party: str) tuple[float, ...][source]

Return vote shares for party across all regions.

The returned tuple contains one vote-share value per region, in the order of self.regions.

Parameters:

party (str) – Party ID

Returns:

The tuple of the percentage of votes that party received in each part of the

partition

Return type:

tuple

seats(party: str) int[source]

Return number of seats that party won.

Parameters:

party (str) – Party name

Returns:

The number of seats that party won.

Return type:

int

total_votes() float[source]

Return total number of votes cast in the election.

Returns:

The total number of votes cast in the election.

Return type:

float

votes(party: str) tuple[float, ...][source]

An alias for counts.

It returns a tuple of the total votes cast for party in each part of the partition.

Parameters:

party (str) – Party ID

Returns:

tuple of the total votes cast for party in each part of the partition

Return type:

tuple

wins(party: str) int[source]

An alias for seats.

Parameters:

party (str) – Party name

Returns:

The number of seats that party won.

Return type:

int

won(party: str, region: Hashable) bool[source]

Determines if party won in the region given by region?”.

Parameters:
  • party (str) – Party ID

  • region (Hashable) – ID of the part of the partition whose votes we want to tally.

Returns:

Answer to “Did party win the region in part region?”

Return type:

bool

class gerrychain.updaters.election.ElectionUpdater(election: Election)[source]

The updater for computing the election results in each part of the partition after each step in the Markov chain. The actual results are returned to the user as an ElectionResults instance.

election

The Election object that this updater is associated with.

Type:

Election

get_previous_values(partition: Partition) Mapping[str, dict[Hashable, float] | None][source]

Returns a dictionary mapping party names to the vote totals that party received in each.

Parameters:

partition (Partition) – The partition whose parent we want to obtain the previous vote totals from.

Returns:

A dictionary mapping party names to the

vote totals that party received in each part of the parent of the current partition.

Return type:

Mapping[str, dict[Hashable, float] | None]

gerrychain.updaters.election.format_part_results(percents_for_party: Mapping[str, Mapping[Hashable, float]], part: Hashable) str[source]

Return A formatted string containing the results for the given part of the partition.

Parameters:
  • percents_for_party (Mapping[str, Mapping[Hashable, float]]) – Party names mapped to a dict containing the percentage of votes that party received in each part of the partition.

  • part (Hashable) – The part whose results to format.

Returns:

A formatted string containing the results for the given part of the partition.

Return type:

str

gerrychain.updaters.election.get_percents(counts: Mapping[Hashable, float], totals: Mapping[Hashable, float]) dict[Hashable, float][source]

Returns a dictionary mapping each part in a partition to the percentage of votes that a party received in that part.

Parameters:
  • counts (dict) – A dictionary mapping each part in a partition to the count of the number of votes that a party received in that part.

  • totals (dict) – A dictionary mapping each part in a partition to the total number of votes cast in that part.

Returns:

A dictionary mapping each part in a partition to the percentage

Return type:

dict