UK Constituency Explorer
  • Hex Map
  • Geographic Map
  • Scatterplot
  • Histogram
  • Box Plot
  • Heatmap
  • Constituency Profile
  • Data Table

Data Table

rawData = FileAttachment("data/constituencies.json").json()

partyColors = ({
  "Con": "#0087DC", "Lab": "#DC241f", "LD": "#FAA61A",
  "Green": "#6AB023", "RUK": "#12B6CF", "SNP": "#FDF38E",
  "PC": "#005B54", "Ind": "#999999", "Other": "#AAAAAA"
})

allVarsMap = [
  {label: "Conservative 2024",       value: "Con24"},
  {label: "Labour 2024",             value: "Lab24"},
  {label: "Lib Dem 2024",            value: "LD24"},
  {label: "Reform 2024",             value: "RUK24"},
  {label: "Green 2024",              value: "Green24"},
  {label: "SNP 2024",                value: "SNP24"},
  {label: "Plaid Cymru 2024",        value: "PC24"},
  {label: "Other 2024",              value: "Other24"},
  {label: "Conservative 2019",       value: "Con19"},
  {label: "Labour 2019",             value: "Lab19"},
  {label: "Lib Dem 2019",            value: "LD19"},
  {label: "Reform/Brexit 2019",      value: "Brexit19"},
  {label: "Green 2019",              value: "Green19"},
  {label: "SNP 2019",                value: "SNP19"},
  {label: "Plaid Cymru 2019",        value: "PC19"},
  {label: "Turnout 2024",            value: "Turnout24"},
  {label: "Turnout 2019",            value: "Turnout19"},
  {label: "Majority 2024",           value: "Majority24"},
  {label: "Brexit Leave (Hanretty)", value: "HanrettyLeave"},
  {label: "Population Density",      value: "c21PopulationDensity"},
  {label: "Age: Under 15",           value: "AgeUnder15"},
  {label: "Age: 16-24",              value: "Age16to24"},
  {label: "Age: 25-34",              value: "Age25to34"},
  {label: "Age: 35-44",              value: "Age35to44"},
  {label: "Age: 45-54",              value: "Age45to54"},
  {label: "Age: 55-64",              value: "Age55to64"},
  {label: "Age: Over 65",            value: "AgeOver65"},
  {label: "Ethnicity: White",        value: "c21EthnicityWhite"},
  {label: "Ethnicity: Asian",        value: "c21EthnicityAsian"},
  {label: "Ethnicity: Black",        value: "c21EthnicityBlack"},
  {label: "Ethnicity: Mixed",        value: "c21EthnicityMixed"},
  {label: "Born in UK",              value: "born_uk"},
  {label: "Religion: Christian",     value: "c21Christian"},
  {label: "Religion: Muslim",        value: "c21Muslim"},
  {label: "Religion: No Religion",   value: "c21NoReligion"},
  {label: "Qualification: None",     value: "c21QualNone"},
  {label: "Qualification: Level 4+", value: "c21QualLevel4"},
  {label: "Housing: Owned Outright", value: "c21HouseOutright"},
  {label: "Housing: Mortgage",       value: "c21HouseMortgage"},
  {label: "Housing: Social Rent",    value: "c21HouseSocialLA"},
  {label: "Housing: Private Rent",   value: "c21HousePrivateLandlord"},
  {label: "No Car",                  value: "c21CarsNone"},
  {label: "Health: Very Good",       value: "c21HealthVeryGood"},
  {label: "Health: Bad/Very Bad",    value: "c21HealthBad"},
  {label: "Employment: Unemployed",  value: "c21Unemployed"},
  {label: "Deprivation: None",       value: "c21DeprivedNone"},
  {label: "Deprivation: 3+ dims",    value: "c21Deprived3"}
]

mapVarsMap = [
  {label: "2024 Winner", value: "Winner24"},
  {label: "2019 Winner", value: "Winner19"},
  ...allVarsMap
]

allVarLabels = Object.fromEntries(allVarsMap.map(v => [v.value, v.label]))
mapVarLabels = Object.fromEntries(mapVarsMap.map(v => [v.value, v.label]))
allRegions   = [...new Set(rawData.map(d => d.Region))].filter(Boolean).sort()
allWinners   = [...new Set(rawData.map(d => d.Winner24))].filter(Boolean).sort()
allConsts    = rawData.map(d => d.ConstituencyName).filter(Boolean).sort()
viewof tableSearch = Inputs.text({label: "Search:", placeholder: "Constituency, region or winner...", width: 400})

tableCols = ["ConstituencyName","Region","Country","Winner24","Winner19","Majority24","Con24","Lab24","LD24","RUK24","Green24","SNP24","PC24","Turnout24","HanrettyLeave","c21QualLevel4","c21EthnicityWhite","AgeOver65","c21PopulationDensity"]

tableHeaders = ({"ConstituencyName":"Constituency","Region":"Region","Country":"Country","Winner24":"Winner 24","Winner19":"Winner 19","Majority24":"Majority%","Con24":"Con%","Lab24":"Lab%","LD24":"LD%","RUK24":"Ref%","Green24":"Grn%","SNP24":"SNP%","PC24":"PC%","Turnout24":"Turnout%","HanrettyLeave":"Leave%","c21QualLevel4":"Degree%","c21EthnicityWhite":"White%","AgeOver65":"Over65%","c21PopulationDensity":"PopDensity"})

filteredTable = {
  const q = tableSearch.toLowerCase();
  return rawData
    .filter(d => !q || (d.ConstituencyName||"").toLowerCase().includes(q) || (d.Region||"").toLowerCase().includes(q) || (d.Winner24||"").toLowerCase().includes(q))
    .map(d => Object.fromEntries(tableCols.map(c => [tableHeaders[c]||c, typeof d[c]==="number" ? +d[c].toFixed(1) : d[c]])));
}

Inputs.table(filteredTable, {rows: 30, sort: "Constituency"})