What’s in the AEC data feed, and how to use it

With an election coming up, it’s probably a good time to post some notes about using Australian election data feeds. This is mainly aimed at any interested programmers who have a use for this sort of data.

I’ve left out any example code here, as what you write will be specific to how you use the data.

Overview

The AEC publishes results on election night, by simply posting zipped files on an FTP server every few minutes. The detailed documentation is at aec.gov.au.

I have experimented with loading the data into a database during a recent by-election with some success. The data model that I assembled for this was:

2016-06-data-model-aec-feed

You will be able to locate many electoral concepts in this data model, as candidates with a particular affiliation receive votes (contest eachother) at different polling places for a a seat in one of the houses. This maps to the more extensive XML format to extract the fields that I was most interested in mapping.

Getting the data

The FTP server is mediafeed.aec.gov.au, and it accepts anonymous login on election night.

Here you will find a numbered folder for the night’s election. Within this, there is a lot of repetition, so you can ignore most of the files straight away. The sub-folders that I suggest loading are Detailed/LightProgress and Detailed/Preload. For example, in a past election, the file layout was:

18126/
18126/Detailed
18126/Detailed/LightProgress
18126/Detailed/LightProgress/aec-mediafeed-Detailed-LightProgress-18126-20150919194400.zip
18126/Detailed/LightProgress/aec-mediafeed-Detailed-LightProgress-18126-20150919194527.zip
18126/Detailed/LightProgress/aec-mediafeed-Detailed-LightProgress-18126-20150919194702.zip
18126/Detailed/LightProgress/aec-mediafeed-Detailed-LightProgress-18126-20150911140244.zip
18126/Detailed/LightProgress/aec-mediafeed-Detailed-LightProgress-18126-20150919195500.zip
18126/Detailed/LightProgress/...
18126/Detailed/Preload
18126/Detailed/Preload/aec-mediafeed-Detailed-Preload-18126-20150911140243.zip

Loading the data

Start with the Preload data. This zip file is available first, and contains the candidate names, polling places, event details, and an initial (zeroed-out) results feed. Using a custom script and a schema like the one I’ve posted above, you will be able to import this into your database.

Next, the LightProgress feed updates will start being added every few minutes from 7pm. These Zip files contain a small piece of XML, each one superseding older files.

I’ve cut down one of these files as an example:

<?xml version="1.0" encoding="utf-8"?>
<MediaFeed Id="e9334806-990e-4773-8b00-7d74fa58b6af" Created="2015-09-19T19:55:00" SchemaVersion="3" EmlVersion="5" xmlns="http://www.aec.gov.au/xml/schema/mediafeed" xmlns:eml="urn:oasis:names:tc:evs:schema:eml" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:xnl="urn:oasis:names:tc:ciq:xsdschema:xNL:2.0" xmlns:ts="urn:oasis:names:tc:evs:schema:eml:ts" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://www.aec.gov.au/xml/schema/mediafeed ../Schema/AEC/aec-mediafeed-results-v3-0.xsd">
  <ManagingAuthority>
    <eml:AuthorityIdentifier Id="AEC">Australian Electoral Commission</eml:AuthorityIdentifier>
  </ManagingAuthority>
  <MessageLanguage>en</MessageLanguage>
  <MessageGenerator>
    <Name>Virtual Tally Room</Name>
    <Environment>PROD</Environment>
    <Site>CDC</Site>
    <Server>DB02</Server>
    <Platform>x64</Platform>
    <Version>9.2.0.28493</Version>
  </MessageGenerator>
  <Cycle Created="2015-09-19T19:54:47">37f177b4-ab20-4073-be85-0edefa5c8e96</Cycle>
  <Results Phase="ElectionNight" Verbosity="LightProgress" Granularity="Detailed">
    <eml:EventIdentifier Id="18126">
      <eml:EventName>Canning By-election</eml:EventName>
    </eml:EventIdentifier>
    <Election>
      <eml:ElectionIdentifier Id="H">
        <eml:ElectionName>House of Representatives By-election for the division of Canning</eml:ElectionName>
        <eml:ElectionCategory>ByElection</eml:ElectionCategory>
      </eml:ElectionIdentifier>
      <House>
        <Contests>
          <Contest Projected="true">
            <eml:ContestIdentifier Id="236">
              <eml:ContestName>Canning</eml:ContestName>
            </eml:ContestIdentifier>
            <Enrolment>112809</Enrolment>
            <FirstPreferences PollingPlacesReturned="0" PollingPlacesExpected="53">
              <Candidate>
                <eml:CandidateIdentifier Id="25424" />
                <BallotPosition>1</BallotPosition>
                <Elected>false</Elected>
                <Votes MatchedHistoric="0">0</Votes>
                <VotesByType>
                  <Votes Type="Ordinary">0</Votes>
                  <Votes Type="Absent">0</Votes>
                  <Votes Type="Provisional">0</Votes>
                  <Votes Type="PrePoll">0</Votes>
                  <Votes Type="Postal">0</Votes>
                </VotesByType>
              </Candidate>
              <!-- (other candidates, ghost candidates) -->
              <Formal>
                <Votes MatchedHistoric="0">0</Votes>
                <VotesByType>
                  <Votes Type="Ordinary">0</Votes>
                  <Votes Type="Absent">0</Votes>
                  <Votes Type="Provisional">0</Votes>
                  <Votes Type="PrePoll">0</Votes>
                  <Votes Type="Postal">0</Votes>
                </VotesByType>
              </Formal>
              <Informal>
                <Votes MatchedHistoric="0">0</Votes>
                <VotesByType>
                  <Votes Type="Ordinary">0</Votes>
                  <Votes Type="Absent">0</Votes>
                  <Votes Type="Provisional">0</Votes>
                  <Votes Type="PrePoll">0</Votes>
                  <Votes Type="Postal">0</Votes>
                </VotesByType>
              </Informal>
              <Total>
                <Votes MatchedHistoric="0">0</Votes>
                <VotesByType>
                  <Votes Type="Ordinary">0</Votes>
                  <Votes Type="Absent">0</Votes>
                  <Votes Type="Provisional">0</Votes>
                  <Votes Type="PrePoll">0</Votes>
                  <Votes Type="Postal">0</Votes>
                </VotesByType>
              </Total>
            </FirstPreferences>
            <TwoCandidatePreferred Restricted="true" PollingPlacesReturned="0" PollingPlacesExpected="53" />
            <TwoPartyPreferred>
              <Coalition>
                <CoalitionIdentifier Id="2" />
                <Votes>0</Votes>
              </Coalition>
              <Coalition>
                <CoalitionIdentifier Id="1" />
                <Votes>0</Votes>
              </Coalition>
            </TwoPartyPreferred>
            <PollingPlaces>
              <PollingPlace>
                <PollingPlaceIdentifier Id="7467" />
                <FirstPreferences />
                <TwoCandidatePreferred Restricted="true" />
              </PollingPlace>
              <!-- (other polling places, ghost candidates) -->
            </PollingPlaces>
          </Contest>
        </Contests>
      </House>
    </Election>
  </Results>
</MediaFeed>

Spatial data

You can also download electorate boundaries as spatial data here to back any visualisations of the results.

The locations of polling places are already encoded in the Preload data file.

Good luck!