MP carbon footprint on expenses

data analysis
An examination of how large the carbon footprint of UK MPs is, if you only look at the travel that they claim on their expenses.
Published

2023-11-27

This is a work in progress. I need to finish converting trips to carbon consumption!

An example - Hey big spender!

Here we’re going to look at the carbon footprint of the travel UK Members of Parliament (MPs) have put on their expenses. First, we will get the data for MPs’ expenses from IPSA. I’ll be looking at the data from the year 2022-2023, as this is the last complete year of data as of 21/11/2023.

Here are the top 30 spenders, by the amount paid for their travel.

Show the code
data = await FileAttachment("data/individualBusinessCosts_22_23.csv").csv({typed:true});
travel_tags = ['Dependant Travel', 'MP Travel', 'Staff Travel'];
travel_data = data
  .filter((expense) => {
    return travel_tags.includes(expense.Category)
  })
  .map((expense) => {
      return {Name: expense.Name, "Amount Claimed": expense['Amount Claimed'], 'Cost Type': expense['Cost Type'] }
      });
total_travel = travel_data.reduce((acc, current) => {
  const existing = acc.find(item => item.Name === current.Name);
   if (existing) {
     existing.TotalClaimed += current["Amount Claimed"];
   } else {
     acc.push({ Name: current.Name, TotalClaimed: current["Amount Claimed"] });
   }
   return acc;
  }, [])
  .sort(
    (a, b) => b.TotalClaimed-a.TotalClaimed
  );
travel_biggest_spenders = total_travel.slice(0, 30).map((spender) => spender.Name);
big_spenders_by_type = travel_data
  .filter((expense) => travel_biggest_spenders.includes(expense.Name))
  .reduce(
    (acc, current) => {
      const existing = acc.find(item => item.Name === current.Name && item['Cost Type'] === current['Cost Type']);
      if (existing) {
        existing['Amount Claimed'] += current['Amount Claimed']
      } else {
        acc.push({ Name: current.Name, 'Amount Claimed': current['Amount Claimed'], 'Cost Type': current['Cost Type']})
      }
    return acc;
    }, []
  );
Show the code
Plot.plot({
  marginBottom:120,
  color: {scheme: "Spectral", legend: true, width: 800, label: "Cost Type"},
  x: { tickRotate:-60},
  y: { grid: true },
  marks: [ Plot.barY(big_spenders_by_type, {x:"Name", y: "Amount Claimed", fill: "Cost Type", sort: {color: "fill", x: "-y"}})]
})

Phew, Steven Bonnar spent nearly £60,000 on travel. A lot of this was spent on air travel. Steven Bonnar is the Scottish National Party (SNP) MP for Coatbridge, Chryston and Bellshill.

Show the code
bonnar_flights = data
                     .filter((expense) => expense.Name === 'Steven Bonnar' && expense['Cost Type'] == 'Air travel')
                     .map((expense) => ({ 'From': expense.From, 'To': expense.To }))
                     .reduce((acc, current) => {
                              const existing = acc.find(item => item.From === current.From && item.To === current.To);
                              if (existing) {
                                existing.Count += 1
                              } else {
                                acc.push({ 'From': current.From, 'To': current.To, 'Count' : 1})
                              }
                              return acc;
                            }, [])
                      .sort((a,b) =>
                        {
                          if (a.From < b.From) { return -1}
                          if (a.From > b.From) { return 1 }
                          return 0
                        }
                      );

Inputs.table(bonnar_flights)

You can see that all of this is him flying from Glasgow, where his constituency is, to London, for Parliament. A Glasgow to London flight takes about an hour and a half. The train takes four and a half hours.

Show the code
sb_flight_stats = [
  {Journey: 'GLA-LCY', Vehicle: 'Aeroplane', 'Time (hours)': 1.5, 'Estimated CO2 (kg)': 101.2, 'Distance to\nparliament (km)': 9.5},
  {Journey: 'GLA-LHR', Vehicle: 'Aeroplane', 'Time (hours)': 1.4, 'Estimated CO2 (kg)': 68.5, 'Distance to\nparliament (km)': 16.7},
  {Journey: 'GLA-LGW', Vehicle: 'Aeroplane', 'Time (hours)': 1.6, 'Estimated CO2 (kg)': 81.4, 'Distance to\nparliament (km)': 27.1},
  {Journey: 'GLA-STN', Vehicle: 'Aeroplane', 'Time (hours)': 1.3, 'Estimated CO2 (kg)': 75.6, 'Distance to\nparliament (km)': 41.2},
  {Journey: 'Glasgow-Euston', Vehicle: 'Train', 'Time (hours)': 4.5, 'Estimated CO2 (kg)': 24.57, 'Distance to\nparliament (km)': 2.4}
];
Inputs.table(sb_flight_stats)

Is this all fair enough then? The honourable member would save up to three hours and ten minutes per trip going by air, right? Getting through the airport takes at least an hour, though, and London Euston is a lot closer to Parliament than, for example, Stansted, shrinking the time advantage.

Let’s have an estimate of the carbon emissions of these trips then.

Show the code
sb_flight_counts = [72, 41, 1, 2, 0]
sb_flight_stats_with_counts = sb_flight_stats.map((journey, index) => 
                                                      ({'Journey': journey.Journey,
                                                        'Count': sb_flight_counts[index],
                                                        'Total CO2 (kg)': sb_flight_counts[index]*journey['Estimated CO2 (kg)']
                                                      }));
Inputs.table(sb_flight_stats_with_counts)

The point of the exercise

All this isn’t just to bash poor Steven Bonnar, against whom I have no particular grudge. It’s always going to be tricky commuting from Glasgow to London. I do think, however, we should look at how much damage to the environment the UK taxpayer is paying for. Here, I’ll be estimating the emissions for each taxpayer-funded trip, then breaking down the dataset to see if anyone could be doing better.

Estimating emissions

How do you estimate emissions from travel then? For some modes of transport, it’s fairly straightforward - there’s a particular value per kilometre, and we assume everything else evens out.

What kinds of expenses are people claiming then?

Show the code
travel_types = new Set(travel_data.map((expense) => expense['Cost Type']))
Show the code
viewof test = {
  const type_elements = [...travel_types].map((type) => html`<li>${type}</li>`)
  return html`<ul>${type_elements}</ul>`
}

Some of these we will discard. We aren’t looking at the emissions of staying in a hotel, because it would be too hard to estimate, and not meaningful to look at here. Other things like railcards and congestion charges don’t have a meaningful emissions figure.

I am curious as to what someone is claiming as the mileage on their bicycle, though. New tyres? Protein bars?