By Nael Shiab, computational journalist for CBC/Radio-Canada.
nael.shiab@radio-canada.ca (PGP key)
The story based on this analysis was published on August 26, 2021. Click here to read it.
The code and the data can be downloaded here.
La version française de cette analyse peut être consultée ici.
While the Canadian population is becoming more diverse, political parties are pressured to be more inclusive. To analyze the diversity of the political landscape through time, Anna Elizabeth Johnson (University of Toronto), Erin Tolley (Carleton University), Melanee Thomas (University of Calgary), and Marc A. Bodet (Université Laval) compiled information on 4,516 candidates who ran in 2008, 2011, 2015 and 2019 federal elections. The detailed methodology can be found here. They received a grant from the Social Sciences and Humanities Research Council to do this work.
To categorize candidates between white, racialized, and Indigenous, the researchers and their team gathered information from the Library of Parliament, Elections Canada, official party and candidate websites, social media, and news media.
In addition to this data, I also retrieved the reviewed financial filings submitted by candidates to Elections Canada, the transposition of the population from the 2003 electoral map to the 2013 one, the proportion of visible minorities per electoral districts from the 2016 census and 2004, 2006, 2008, 2011, 2016, and 2019 electoral results.
In the Canadian census, the respondents self-identified as a visible minority (or not if they didn’t consider belonging to one). In the candidate data, it’s the research team that categorized the politicians. However, the team looked as much as possible for documents in which the candidates declared if they considered themselves as a visible minority or not.
I have matched “Aboriginal identity” and “Visible minority” from the Canadian census with “Indigenous” and “Racialized” from the candidate data. The research team used the same definitions.
In the candidate data, I have filtered out twelve candidates (0.3 % of total) that weren’t categorized between white, Indigenous, or racialized and nine candidates (0.2 % of total) that were categorized as non-binary. Their numbers are too small to draw conclusions.
I analyze the proportion of white, racialized, and Indigenous candidates in 2015 and 2019 elections in relation to the weight of these groups in the 2016 census. For the 2019 election, we have to keep in mind this three years gap. According to population projections from Statistic Canada, visible minorities and the Aboriginal population grew faster than the rest of the population. So the 2016 census could be seen as a low baseline for 2019.
For the 2008 and 2011 elections, the electoral map was different and we should use the 2006 and 2011 census releases. While it could be interesting to retrieve and analyze all of this, I haven’t done it to focus on the most up-to-date data.
To identify the party strongholds, we need to work with two different electoral maps that don’t perfectly match. With a threshold of at least 66 % of the population shared between old and new electoral districts, I’ve been able to match 87 % of the districts from the new map to the ones from the old map. We have to keep in mind that new districts are often created in urban areas, which have a more diverse population than rural areas.
In our definition, a stronghold is a district won two times in a row by a party during federal elections with at least a 10 % margin. 55 % of electoral districts were party strongholds in 2008-2011. This proportion dropped to 36 % in 2015-2019. The Bloc québécois lost all of its strongholds. The Conservative Party had 22 % of the strongholds in 2008-2011 compared to 72 % of them in 2015-2019.
I used the reviewed financial filing submitted by candidates to Elections Canada. Elections Canada is not done reviewing all documents from all candidates. After exclusion of the Green Party (see below), I found a match for 3,842 of them (92 % of the total).
Even though I imported many variables from the financial filings, my main focus was on the monetary and non-monetary transfers from the party or party association to the candidates. In the analysis, when I refer to “money transfers”, it includes non-monetary transfers as well. These transfers represent between 70 % and 90 % of the campaign resources for candidates, depending on the party.
In the candidate data, we have the Green party candidates for 2019 only and I have been able to match financial filings to only 16 % of them. Also, the Green party won less than 1 % of the seats. For all these reasons, I excluded the Green candidates in the main analysis. Still, I’ve calculated some figures for this party (see end of this document).
To have more representative trends and to avoid groups with only one or two candidates, I pooled the 2015 and 2019 candidates together and the 2008 and 2011 candidates together. These elections shared the same electoral maps (308 seats in 2008 and 2011 / 338 seats in 2015 and 2019).
Q1: What is the representation of white, Indigenous, racialized, male, and female candidates compared to the general population?
Q2: What is the win ratio for white, Indigenous, racialized, male, and female candidates?
Q3: Do white, Indigenous, racialized, male, and female candidates receive the same resources for their campaign from their party and districts associations?
Q4: Do white, Indigenous, racialized, male, and female candidates are as often running in party strongholds when compared to each other?
Q5: Do white, Indigenous, racialized, male, and female candidates are as often running as an incumbent when compared to each other?
We made a distinction between incumbents and non-incumbents when answering all questions, not just question 5.
Figures are for the 2015-2019 general elections.
White men represent 36 % of the Canadian population, but 52 % of all candidates. And after election day, 62 % of elected candidates are white men.
One of the reasons for this imbalance: incumbency. Overall, 24 % of all candidates are incumbents and 65 % of them are white men. Incumbents are 2,6 more often elected compared to non-incumbents. They receive 76 % (+$41,520) more money/resources from their party and political associations. In strongholds, 71 % of candidates are incumbent.
The Canadian population and the political candidates are getting more diverse elections after elections. With white men being more often incumbent than other groups, the pace of change of the political landscape is slower than in the general population.
But incumbency is not the only factor at play. When we focus on non-incumbents, inequalities remain.
As said before, 36 % of the Canadian population are white men. But among non-incumbent candidates, this ratio is 48 %. And among elected non-incumbent candidates, it’s 57 %.
Non-incumbent white men are 15 % (compared to racialized men) to 158 % (compared to Indigenous women) more often elected than other groups. The only exception is Indigenous men (38 % more than white men).
Non-incumbent white men have between 3 % (+$1,398, compared to racialized women) and 21 % (+$9,857, compared to Indigenous women) more resources transferred to them by their party or political associations. The only exception is the racialized men (12 % - $6,450 more money than white men).
In party strongholds, 72 % of non-incumbent candidates are white men.
We can also see how being a woman influences all these numbers. Overall, men of each group (white, racialized, Indigenous) are more often elected than women of the same group. Men are more often incumbents than women of the same group. When non-incumbent, men also get more money transfers than women of the same group. And no other group is more disadvantaged and underfunded than Indigenous women.
The 2015-2019 elections were more diverse than the 2008-2011 elections.
In the Bloc québécois, 62 % of all candidates and 67 % of elected candidates were white men in 2015-2019. It was the least diverse party (95 % of candidates and 98 % of elected candidates were white).
In the Conservative party, 62 % of all candidates and 77 % of elected candidates were white men in 2015-2019.
In the Liberal party, 51 % of all candidates and 53 % of elected candidates were white men in 2015-2019. This party had the most diverse pool of elected candidates.
The NDP had the most diverse pool of candidates in 2015-2019. 42 % of all candidates were white men in 2015-2019. Still, 56 % of its elected candidates were white men.
We import the packages needed for this analysis.
library(readr)
library(dplyr)
library(tidyr)
library(stringr)
library(ggplot2)
library(viridis)
library(ggh4x)
library(jsonlite)
theme_set(theme_light())
knitr::opts_chunk$set(fig.width=5, fig.height=3)
The candidate data is in a CSV file. We add a column gender_raceIndig in which we concatenate the gender and the visible minority categories of candidates. We also create an abbreviated version gender_raceIndig_abrev for the charts.
data_candidates <- read_csv("./data/candidates.csv") %>%
select(-trail) %>%
mutate(
eyear = as.character(eyear),
ndistrict = as.character(ndistrict),
gender_raceIndig = paste0(gender, "-", raceIndig),
gender_raceIndig_abrev = case_when(
gender_raceIndig == "Male-White" ~ "Male-W",
gender_raceIndig == "Male-Racialized" ~ "Male-R",
gender_raceIndig == "Male-Indigenous" ~ "Male-I",
gender_raceIndig == "Female-White" ~ "Female-W",
gender_raceIndig == "Female-Racialized" ~ "Female-R",
gender_raceIndig == "Female-Indigenous" ~ "Female-I",
TRUE ~ gender_raceIndig
)
)
head(data_candidates, 3)
We import the transposition of the population from the 2003 electoral map to the 2013 electoral map. We identify 2013 electoral districts that have at least 66 % of the population from a 2003 electoral district. There are 295 (87 %) of them.
populationTransposition <- read_csv("./data/TRANSPOSITION_338FED.csv", skip=4) %>%
select(`2013 FED Number`, `2013 FED - Population`, `2003 FED Number from which the 2013 FED Number is constituted`, `Population transferred to 2013 FED`) %>%
unique() %>%
mutate(perc = round(`Population transferred to 2013 FED` / `2013 FED - Population` * 100) ) %>%
filter(perc >= 66) %>%
select(`2013 FED Number`, `2003 FED Number from which the 2013 FED Number is constituted`) %>%
rename(
ndistrict = `2013 FED Number`,
ndistrictPrevious = `2003 FED Number from which the 2013 FED Number is constituted`
) %>%
mutate(
ndistrict = as.character(ndistrict),
ndistrictPrevious = as.character(ndistrictPrevious)
)
head(populationTransposition, 3)
We import the electoral results. The 2006 and the 2004 results don’t have the id for the electoral districts. We harmonize everything. Some names changed between 2004 and 2006. We updated them manually in the 2004 CSV file with table 14 from the page results.
results2019 <- read_csv("./data/electoralResults/2019.csv") %>% mutate(eyear = "2019")
results2015 <- read_csv("./data/electoralResults/2015.csv") %>% mutate(eyear = "2015")
results2011 <- read_csv("./data/electoralResults/2011.csv") %>% mutate(eyear = "2011")
results2008 <- read_csv("./data/electoralResults/2008.csv") %>% mutate(eyear = "2008")
districts2003 <- results2008 %>%
select(`Electoral District Name/Nom de circonscription`, `Electoral District Number/Numéro de circonscription`) %>%
unique()
results2006 <- read_csv("./data/electoralResults/2006.csv") %>%
rename(`Electoral District Name/Nom de circonscription` = `Electoral District/Circonscription`) %>%
mutate(eyear = "2006")
results2006 <- left_join(results2006, districts2003)
results2004 <- read_csv("./data/electoralResults/2004.csv") %>%
rename(
`Electoral District Name/Nom de circonscription` = District,
`Candidate/Candidat` = Candidate,
`Candidate Residence/Résidence du candidat` = Residence,
`Candidate Occupation/Profession du candidat` = Occupation,
`Votes Obtained/Votes obtenus` = `Number of Votes`,
`Percentage of Votes Obtained /Pourcentage des votes obtenus` = `Number of Votes Percent`,
`Majority/Majorité` = `Number Majority`,
`Majority Percentage/Pourcentage de majorité` = `Majority Percent`
) %>%
mutate(eyear = "2004")
results2004 <- left_join(results2004, districts2003)
results <- rbind(results2019, results2015, results2011, results2008, results2006, results2004) %>% select(`Electoral District Number/Numéro de circonscription`, `Candidate/Candidat`, `Majority Percentage/Pourcentage de majorité`, eyear) %>%
rename(
ndistrict = `Electoral District Number/Numéro de circonscription`,
name = `Candidate/Candidat`,
voteDifference = `Majority Percentage/Pourcentage de majorité`
) %>%
mutate(
party = str_split(name, "/", simplify = T)[,2]
) %>%
mutate(
ndistrict = as.character(ndistrict),
party = case_when(
party == "Libéral" ~ "Liberal",
party == "Conservateur" ~ "Conservative",
party == "conservateur" ~ "Conservative",
party == "NPD-Nouveau Parti démocratique" ~ "NDP",
party == "N.P.D." ~ "NDP",
party == "Bloc Québécois" ~ "Bloc",
party == "Parti Vert" ~ "Green",
TRUE ~ party
)
)
head(results, 3)
We import the 2016 census data aggregated per electoral district. We retrieve the “visible minority” population and the number of people with an “Aboriginal identity”. We deduce the white population from this and calculate the percentage for each group. We harmonize the names with the candidate data. We also add a column majorityGroup in which we specify if one of the groups makes 50 % or more of the population.
all_data_census <- read_csv("./data/census/data.csv") %>%
select(`GEO_CODE (POR)`, `DIM: Profile of Federal Electoral Districts (2013 Representation Order) (2247)`, `Dim: Sex (3): Member ID: [1]: Total - Sex`, `Dim: Sex (3): Member ID: [2]: Male`, `Dim: Sex (3): Member ID: [3]: Female`) %>%
rename(
"ndistrict" = `GEO_CODE (POR)`,
"variable" = `DIM: Profile of Federal Electoral Districts (2013 Representation Order) (2247)`,
"count" = `Dim: Sex (3): Member ID: [1]: Total - Sex`,
"men" = `Dim: Sex (3): Member ID: [2]: Male`,
"women" = `Dim: Sex (3): Member ID: [3]: Female`
) %>%
filter(
variable %in% c("Population, 2016", "Total visible minority population", "Aboriginal identity")
)
data_census <- all_data_census %>%
select(-men, -women) %>%
pivot_wider(names_from = variable, values_from = count) %>%
rename(
"population" = `Population, 2016`,
"IndigenousCount" = `Aboriginal identity`,
"RacializedCount" = `Total visible minority population`
) %>%
mutate(
WhiteCount = population - IndigenousCount - RacializedCount,
White = round(WhiteCount / population * 100),
Indigenous = round(IndigenousCount / population * 100),
Racialized = round(RacializedCount / population * 100),
majorityGroup = case_when(
Indigenous >= 50 ~ "Indigenous",
Racialized >= 50 ~ "Racialized",
White >= 50 ~ "White",
TRUE ~ "None"
)
)
head(data_census, 3)
We manually create a data_census_gender dataframe as well, based on the 2016 census data, to have distinct numbers for men and women.
data_census_gender <- data.frame(
rbind(
c("01", "Male", "White", round((17264200 - 3725090 - 813520) / 35151728 * 100,1)),
c("01", "Male", "Racialized", round(3725090 / 35151728 * 100, 1)),
c("01", "Male", "Indigenous", round(813520 / 35151728 * 100, 1)),
c("01", "Female", "White", round((17887530 - 3949490 - 860260) / 35151728 * 100, 1)),
c("01", "Female", "Racialized", round(3949490 / 35151728 * 100, 1)),
c("01", "Female", "Indigenous", round(860260 / 35151728 * 100, 1)),
c("24", "Male", "White", round( (4016760 - 505180 - 91890 ) / 8164361 * 100, 1)),
c("24", "Male", "Racialized", round(505180 / 8164361 * 100, 1)),
c("24", "Male", "Indigenous", round(91890 / 8164361 * 100, 1)),
c("24", "Female", "White", round( (4147605 - 527190 - 90995 ) / 8164361 * 100, 1)),
c("24", "Female", "Racialized", round(527190 / 8164361 * 100, 1)),
c("24", "Female", "Indigenous", round(90995 / 8164361 * 100, 1))
)
)
colnames(data_census_gender) <- c("ndistrict", "gender", "raceIndig", "perc")
data_census_gender <- data_census_gender %>%
mutate(
geo = case_when(
ndistrict == "01" ~ "Canada",
ndistrict == "24" ~ "Québec"
),
gender_raceIndig = paste0(gender,"-", raceIndig),
perc = as.numeric(perc)
)
head(data_census_gender,3)
We import the reviewed financial filings from Election Canada for 2008, 2011, 2015, and 2019 general elections. They changed through time so we harmonize them.
financialReturns2008 = read_csv("./data/financialReturns/2008.csv", skip=4) %>%
mutate(
financialName = paste(Given_name_of_candidate, Family_name_of_candidate, sep=" "),
eyear = "2008"
) %>%
select(eyear, financialName, Political_party, Electoral_district, Total_contributions, Total_loans_received, Total_monetary_transfers_received_from_registered_parties, Total_non_monetary_transfers_received_from_registered_parties, Total_monetary_transfers_received_from_registered_associations, Total_non_monetary_transfers_received_from_registered_associations, Total_monetary_transfers_received, Total_non_monetary_transfers_received, Total_transfers_received, Grand_total_contributions) %>%
rename(
"party" = Political_party,
"ndistrictname" = Electoral_district,
"contributions" = Total_contributions,
"loans" = Total_loans_received,
"monetaryTransfersFromParty" = Total_monetary_transfers_received_from_registered_parties,
"nonMonetaryTransfersFromParty" = Total_non_monetary_transfers_received_from_registered_parties,
"monetaryTransfersFromAssociation" = Total_monetary_transfers_received_from_registered_associations,
"nonMonetaryTransfersFromAssociation" = Total_non_monetary_transfers_received_from_registered_associations,
"totalMonetaryTransfers" = Total_monetary_transfers_received,
"totalNonMonetaryTransfers" = Total_non_monetary_transfers_received,
"totalTransfers" = Total_transfers_received,
"grandTotalContributions" = Grand_total_contributions
)
financialReturns2011 = read_csv("./data/financialReturns/2011.csv", skip = 4) %>%
mutate(
financialName = paste(Given_name_of_candidate, Family_name_of_candidate, sep=" "),
eyear = "2011"
) %>%
select(eyear, financialName, Political_party, Electoral_district, Total_contributions, Total_loans_received, Total_monetary_transfers_received_from_registered_parties, Total_non_monetary_transfers_received_from_registered_parties, Total_monetary_transfers_received_from_registered_associations, Total_non_monetary_transfers_received_from_registered_associations, Total_monetary_transfers_received, Total_non_monetary_transfers_received, Total_transfers_received, Grand_total_contributions) %>%
rename(
"party" = Political_party,
"ndistrictname" = Electoral_district,
"contributions" = Total_contributions,
"loans" = Total_loans_received,
"monetaryTransfersFromParty" = Total_monetary_transfers_received_from_registered_parties,
"nonMonetaryTransfersFromParty" = Total_non_monetary_transfers_received_from_registered_parties,
"monetaryTransfersFromAssociation" = Total_monetary_transfers_received_from_registered_associations,
"nonMonetaryTransfersFromAssociation" = Total_non_monetary_transfers_received_from_registered_associations,
"totalMonetaryTransfers" = Total_monetary_transfers_received,
"totalNonMonetaryTransfers" = Total_non_monetary_transfers_received,
"totalTransfers" = Total_transfers_received,
"grandTotalContributions" = Grand_total_contributions
)
financialReturns2015 = read_csv("./data/financialReturns/2015.csv", skip = 4) %>%
mutate(
financialName = paste(Candidate_last_name, Candidate_first_name, sep=" "),
eyear = "2015"
) %>%
select(eyear, financialName, Political_Affiliation, Electoral_district, Total_contributions_Individuals, Total_loans_received, Total_monetary_transfers_received_from_registered_party, Total_non_monetary_transfers_received_from_registered_party, Total_monetary_transfers_received_from_registered_associations, Total_non_monetary_transfers_received_from_registered_associations, Total_monetary_transfers_received, Total_non_monetary_transfers_received, Total_transfers_received, Grand_total_contributions) %>%
rename(
"party" = Political_Affiliation,
"ndistrictname" = Electoral_district,
"contributions" = Total_contributions_Individuals,
"loans" = Total_loans_received,
"monetaryTransfersFromParty" = Total_monetary_transfers_received_from_registered_party,
"nonMonetaryTransfersFromParty" = Total_non_monetary_transfers_received_from_registered_party,
"monetaryTransfersFromAssociation" = Total_monetary_transfers_received_from_registered_associations,
"nonMonetaryTransfersFromAssociation" = Total_non_monetary_transfers_received_from_registered_associations,
"totalMonetaryTransfers" = Total_monetary_transfers_received,
"totalNonMonetaryTransfers" = Total_non_monetary_transfers_received,
"totalTransfers" = Total_transfers_received,
"grandTotalContributions" = Grand_total_contributions
)
financialReturns2019 = read_csv("./data/financialReturns/2019.csv", skip = 4) %>%
mutate(
financialName = paste(Candidate_last_name, Candidate_first_name, sep=" "),
eyear = "2019"
) %>%
select(eyear, financialName, Political_Affiliation, Electoral_district, Total_contributions_Individuals, Total_loans_received, Total_monetary_transfers_received_from_registered_party, Total_non_monetary_transfers_received_from_registered_party, Total_monetary_transfers_received_from_registered_associations, Total_non_monetary_transfers_received_from_registered_associations, Total_monetary_transfers_received, Total_non_monetary_transfers_received, Total_transfers_received, Grand_total_contributions) %>%
rename(
"party" = Political_Affiliation,
"ndistrictname" = Electoral_district,
"contributions" = Total_contributions_Individuals,
"loans" = Total_loans_received,
"monetaryTransfersFromParty" = Total_monetary_transfers_received_from_registered_party,
"nonMonetaryTransfersFromParty" = Total_non_monetary_transfers_received_from_registered_party,
"monetaryTransfersFromAssociation" = Total_monetary_transfers_received_from_registered_associations,
"nonMonetaryTransfersFromAssociation" = Total_non_monetary_transfers_received_from_registered_associations,
"totalMonetaryTransfers" = Total_monetary_transfers_received,
"totalNonMonetaryTransfers" = Total_non_monetary_transfers_received,
"totalTransfers" = Total_transfers_received,
"grandTotalContributions" = Grand_total_contributions
)
financialReturns <- rbind(financialReturns2008, financialReturns2011, financialReturns2015, financialReturns2019) %>%
mutate(
party = case_when(
party == "Conservative Party of Canada" ~ "Conservative",
party == "Liberal Party of Canada" ~ "Liberal",
party == "New Democratic Party" ~ "NDP",
party == "Bloc Québécois" ~ "Bloc",
party == "Green Party of Canada" ~ "Green",
TRUE ~ party
)
) %>%
mutate_if(is.numeric, ~replace_na(., 0))
head(financialReturns, 3)
First, we add the names of the candidates.
data <- left_join(data_candidates, select(results, c("ndistrict", "name", "eyear", "party")), by = c("eyear", "ndistrict", "party"))
head(data, 3)
We identify the party strongholds and add them to our data. In our definition, a stronghold has to be won two federal elections in a row by the same party with at least a 10 % margin. Because the 2011 and 2008 elections used the 2003 electoral map while the 2015 and 2019 ones use the 2013 electoral map, we have to use the transposition of population. We create a function to simplify our code and a chart to visualize the number of strongholds per federal election (Green party excluded).
resultsElected <- results %>%
filter(is.na(voteDifference) == FALSE)
checkStrongholds <- function (year0, year1, year2, strongholds) {
threshold <- 10
resultsElectedYear0 <- filter(resultsElected, eyear == year0)
resultsElectedYear1 <- filter(resultsElected, eyear == year1)
resultsElectedYear2 <- filter(resultsElected, eyear == year2)
for (i in rownames(resultsElectedYear0)) {
ndistrictYear0 <- resultsElectedYear0[i, "ndistrict"]$ndistrict
ndistrictYear0Transposition <- ""
if (year0 %in% c("2019", "2015")) {
ndistrictYear0Transposition <- filter(populationTransposition, ndistrict == ndistrictYear0)
if (nrow(ndistrictYear0Transposition) == 0) {
ndistrictYear0Transposition = NA
} else {
ndistrictYear0Transposition = ndistrictYear0Transposition$ndistrictPrevious
}
}
if (is.na(ndistrictYear0Transposition) == FALSE) {
partyYear1 <- ""
voteDifferenceYear1 <- ""
if (year1 == "2011") {
dataYear1 <- filter(resultsElectedYear1, ndistrict == ndistrictYear0Transposition)
partyYear1 <- dataYear1$party
voteDifferenceYear1 <- dataYear1$voteDifference
} else {
dataYear1 <- filter(resultsElectedYear1, ndistrict == ndistrictYear0)
partyYear1 <- dataYear1$party
voteDifferenceYear1 <- dataYear1$voteDifference
}
partyYear2 <- ""
voteDifferenceYear2 <- ""
if (year2 %in% c("2011", "2008")) {
dataYear2 <- filter(resultsElectedYear2, ndistrict == ndistrictYear0Transposition)
partyYear2 <- dataYear2$party
voteDifferenceYear2 <- dataYear2$voteDifference
} else {
dataYear2 <- filter(resultsElectedYear2, ndistrict == ndistrictYear0)
partyYear2 <- dataYear2$party
voteDifferenceYear2 <- dataYear2$voteDifference
}
stronghold <- ""
if (partyYear1 == partyYear2 & voteDifferenceYear1 >= threshold & voteDifferenceYear2 >= threshold) {
stronghold <- partyYear1
} else {
stronghold <- "none"
}
strongholds[nrow(strongholds) + 1, ] <- c(year0, ndistrictYear0, stronghold)
}
}
return(strongholds)
}
strongholds <- data.frame(matrix(ncol = 3, nrow = 0))
colnames(strongholds) <- c("eyear", "ndistrict", "stronghold")
strongholds <- checkStrongholds("2019", "2015", "2011", strongholds)
strongholds <- checkStrongholds("2015", "2011", "2008", strongholds)
strongholds <- checkStrongholds("2011", "2008", "2006", strongholds)
strongholds <- checkStrongholds("2008", "2006", "2004", strongholds)
data <- left_join(data, strongholds) %>%
mutate(
inStronghold = case_when(
party == stronghold ~ TRUE,
TRUE ~ FALSE
)
)
head(data, 3)
data %>%
filter(stronghold != "Green", is.na(stronghold) == FALSE) %>%
select(eyear, ndistrict, stronghold) %>%
unique() %>%
group_by(eyear, stronghold) %>%
summarize(count = n()) %>%
ggplot(aes(x=stronghold, y=count, fill=stronghold, label=count)) +
facet_wrap(~eyear) +
scale_fill_viridis(discrete = T) +
geom_col() +
geom_text(vjust=-.5) +
expand_limits(y=240) +
theme(
legend.position = "none",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.title = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank()
)