Election Visualization with R

Harish Nagpal
Analytics Vidhya
Published in
10 min readFeb 21, 2020

--

Photo by Elliott Stallion on Unsplash

Did you ever watch election results on TV channels? The excitement, the drama and the action is incomparable. Whether its Indian elections results or US elections results, the screaming TV presenters will increase your adrenaline. The results changes ever minute. Different TV channels show different results as the news of counting pours in. Slowly the excitement peaks in. Every party claims that they are winning. Its a new world of action packed drama which can even beat Bond movie on that day.

But one thing is common among all the TV channels i.e. visualization of election results. Whichever TV channel shows the best visualizations wins the battle for that day.

Presenting election results is an art and that can be only achieved with visualizations.

Election results can be presented in different ways and here are few of them:

  1. Country maps chart

2. Parliament Chart

3. Bar Chart

4. Bubble Chart

5. Tree charts

6. Animated Charts

7. Scatter Charts

8. Lollipop charts

9. Donuts Chart

10. Bulls eye chart and so on.

However when it comes to viewing, country maps are best in terms of viewing and most appealing. There are many open source election results Software in the market and you can find a few here

If you know Tableau then you can also draw election results on it very easily.

But all these visualizations can be done in R easily. You just need a fair amount of knowledge of coding in R, state of the art visualization package ggplot2, Shape file of the region/country for which you are visualizing election results, Election results of the region/country in excel/csv and last but not the least little patience.

In this article I will show you how to visualize election results in R and I would be taking General Election results of India 2019. Since I have taken the results from various websites, if you find any mistake then do let me know. This article is being written from education point of view and you can take it as a base for visualization of election results or any visualization project you are doing. I have mentioned the results source in almost all the charts. However you can find the final results of General Election results of India 2019 here.

I had a difficulty in searching correct India files with correct India and State boundaries. I tried searching shape of file India on the net and finally got one here.

When you download a shape file, other files also gets downloaded in the different formats ie .shp, .dbf, .shx, .sbn and .sbx.

Shape file is a huge complex file. As per Wikipedia, a shape file format is a geospatial vector data format for geographic information system (GIS) software. It is developed and regulated by Esri as a mostly open specification for data interoperability among Esri and other GIS software products. It contains longitude and latitude data of various places. Read more about shape file here.

Let us start visualization in R.

To do visualization with a shape file you will need various various R packages which are given below:

library(ggplot2)
library(maptools)
library(rgeos)
library(ggmap)
library(scales)
library(RColorBrewer)
library(sf)
library(rgdal)
library(dplyr)
library(plotly)
library(mapproj)

Set a random seed and load the shape file.

set.seed(8000)shp <- readOGR(‘D:/Harish/R practice projects/india/Election/india_pc_2019.shp’) # India shape file With Telangana, Chattisgarhand J&K
names(shp)
[1] “ST_NAME” “PC_NAME” “ST_CODE” “PC_CODE” “Res”

If you do an str on a shape file, you will get a big result on the screen. Pasting a part of that out put here:

str(shp).. .. .. .. .. .. ..@ area : num 1.35
.. .. .. .. .. .. ..@ hole : logi FALSE
.. .. .. .. .. .. ..@ ringDir: int 1
.. .. .. .. .. .. ..@ coords : num [1:5812, 1:2] 80.2 80.2 80.2 80.2 80.2 …
.. .. .. ..@ plotOrder: int 1
.. .. .. ..@ labpt : num [1:2] 80.1 29.9
.. .. .. ..@ ID : chr “19”
.. .. .. ..@ area : num 1.35

The field ID is important here. Let us plot the shape file. See Plot 1 as given below.

plot(shp)
India Map with shape file

I did some feature engineering and data cleaning on the shape file, as I found that some places names’ were common in two status. So I had to correct them.

# manually separating some places as per State

shp$PC_NAME[ shp$RId == 3] <- “HAMIRPUR, HIMACHAL PRADESH”
shp$PC_NAME[ shp$RId == 119] <- “HAMIRPUR, UTTAR PRADESH”
shp$PC_NAME[shp$RId == 135] <- “MAHARAJGANJ, UTTAR PRADESH”
shp$PC_NAME[shp$RId == 171] <- “MAHARAJGANJ, BIHAR”
shp$PC_NAME[shp$RId == 181] <- “AURANGABAD, BIHAR”
shp$PC_NAME[shp$RId == 359] <- “AURANGABAD, MAHARASHTRA”

Make a data frame from this shape file.

#making dataframeshp.f <- fortify(shp, region=”PC_NAME”)
head(shp.f)
long lat order hole piece id group
1 78.33642 19.88331 1 FALSE 1 ADILABAD(ST) ADILABAD(ST).1
2 78.33689 19.88322 2 FALSE 1 ADILABAD(ST) ADILABAD(ST).1
3 78.33868 19.88331 3 FALSE 1 ADILABAD(ST) ADILABAD(ST).1
4 78.34025 19.88344 4 FALSE 1 ADILABAD(ST) ADILABAD(ST).1
5 78.34203 19.88310 5 FALSE 1 ADILABAD(ST) ADILABAD(ST).1
6 78.34388 19.88283 6 FALSE 1 ADILABAD(ST) ADILABAD(ST).1
> nrow(shp.f) #no of records
[1] 3199318

Let us load our election data. Before loading the data, I had to do feature engineering on election results file to match it with shape file. The spellings name of PCs were different in both the files. I had to correct them manually.

Results <- read.csv(‘D:/Harish/R practice projects/india/election/Data/2019 Results New.csv’)
names(Results)
> names(Results)
[1] “From.election.2019” “comp1” “id” “comp2”
[5] “id_1” “Winning.Candidate” “Party” “W_Alliance”
[9] “Losing.Candidate” “Party.1” “Alliance” “X.REF.”

Let us view the data. It has 543 records. For one parliamentary constituency, election did not happen in that period. And it was held later. That result is not included here in this article.

> head(Results, n = 2)
From.election.2019 comp1 id comp2 id_1 Winning.Candidate Party W_Alliance
1 ADILABAD(ST) ADILABAD(ST) ADILABAD(ST) ADILABAD(ST) ADIL Soyam Bapu Rao BJP NDA
2 AGRA (SC) AGRA (SC) AGRA (SC) AGRA (SC) AGRA Satyapal Singh Baghel BJP NDA
Losing.Candidate Party.1 Alliance X.REF.
1 Godam Nagesh TRS OTHERS #REF!
2 Manoj Kumar Soni BSP MGB/OTHERS #REF!
> nrow(Results)
[1] 543

The ‘ID’ field contains Parliamentary Constituency Name. This field is present in both files. So we will use this field to merge both the files and then order this file.

#merging the data by constituencymerged <-merge(shp.f,Results, by=”id”)final.data<-merged[order(merged$order), ]head(final.data, n = 2)> head(final.data, n = 2)
id long lat order hole piece group From.election.2019 comp1
5568 ADILABAD(ST) 78.33642 19.88331 1 FALSE 1 ADILABAD(ST).1 ADILABAD(ST) ADILABAD(ST)
5569 ADILABAD(ST) 78.33689 19.88322 2 FALSE 1 ADILABAD(ST).1 ADILABAD(ST) ADILABAD(ST)
comp2 id_1 Winning.Candidate Party W_Alliance Losing.Candidate Party.1 Alliance X.REF.
5568 ADILABAD(ST) ADIL Soyam Bapu Rao BJP NDA Godam Nagesh TRS OTHERS #REF!
5569 ADILABAD(ST) ADIL Soyam Bapu Rao BJP NDA Godam Nagesh TRS OTHERS #REF!

Let us see the field names in final file.

> names(merged)
[1] “id” “long” “lat” “order”
[5] “hole” “piece” “group” “From.election.2019”
[9] “comp1” “comp2” “id_1” “Winning.Candidate”
[13] “Party” “W_Alliance” “Losing.Candidate” “Party.1”
[17] “Alliance” “X.REF.”

I wanted to represent political parties by color. So I wrote a small code for that.

cols <- c(
“TRS” = “darkseagreen3”,
“NDA” = “darkorange”,
“UPA” = “blue”,
“MGB” = “green”,
“YSRC” = “darksalmon”,
“TMC” = “deeppink1”,
“BJD” = “darkorchid2”,
“NA” = “cyan”,
“OTHERS”= “red”
)

Country Map Chart

We have prepared the final file. Let us start to present this data on India’s map. I will use ggplot2 to make this chart. I will use aesthetics — ggpolygon to plot data on India’s map. See code below:

chart <- ggplot()+
geom_polygon(data = final.data,aes(x = long, y = lat, group = group,
fill = W_Alliance,color=id),color=”black”,size = 0.25) +
coord_map() +
xlab(‘Longitude’)+
ylab(‘Latitude’) +
labs(title=”Indian Elections — 2019 — Party wise Results”,
caption = “SOURCE: oneindia.com, indiatoday.in, eci.gov.in & wiki”) +
scale_fill_manual(name=”id”, values = cols) + theme(legend.title=element_blank())

We have got the visualization in the chart variable. Let us print this.

# prining chart output
print(chart)

See below the final results on India’s map

India General Election Results 2019

What if you want to display the results from a State. That is pretty easy. I added a State variable and then filtered the data on a State. Let us see the code below for State = ‘UP’

State.data <- filter(final.data, State == ‘UP’)# Making final Indian Map
chart_state <- ggplot()+
geom_polygon(data = State.data,aes(x = long, y = lat, group = group,
fill = W_Alliance,color=id),color=”black”,size = 0.25) +
coord_map() +
xlab(‘Longitude’)+
ylab(‘Latitude’) +
labs(title=”Indian Elections — 2019 — Party wise Results — Uttar Pradesh”,
caption = “SOURCE: oneindia.com, indiatoday.in, eci.gov.in & wiki”) +
scale_fill_manual(name=”id”, values = cols) + theme(legend.title=element_blank())
# prining chart output
print(chart_state)
Uttar Pradesh General Elections 2019

Parliament Chart

Now let is make a Parliament chart. R has a library called ‘ggparliament’ which helps in presenting the data like an arc or like MPs sit in a parliment.

Let us write the code for this. I used below libraries to make this chart:

library(ggplot2)
library(ggparliament)
library(readr)
library(dplyr)

I already did feature engineered my data to show the Parties and number of seats won by various parties.

#get the data
Results <- read.csv(‘D:/Harish/R practice projects/india/election/Data/NoOfSeats 2019.csv’, stringsAsFactors = T, na.strings=c(“”,”NA”))
head(Results)> head(Results)
party_short seats government
1 BJP 303 1
2 Congress 52 0
3 DMK 24 0
4 TMC 22 0
5 YSRC 22 0
6 Shiv Sena 18 1

You can draw the data in different shapes like horseshoe or semicircle. I am choosing semicircle here.

#Decide type of parliament
Parlia_semicircle <- parliament_data(election_data = Results,
type = “semicircle”,
parl_rows = 12,
party_seats = Results$seats)

Now let us draw our parliament chart with ggplot. Since I want different parties to be represented in different color, I will use ‘scale_color_manual’ aesthetics to pass party name and the color it will represent. Full code is given below. The theme being used in theme ggparliament.

ind <- ggplot(Parlia_semicircle, aes(x =x, y = y, colour = party_short)) +
geom_parliament_seats(stat = “identity”,position = “identity”,size = 5) +
theme_ggparliament() +
labs(colour = “Parties”,
title = “Indian 2019 Parliament”, legend.position = “center”) +
scale_color_manual(values=c(‘BJP’=’#FF8C00',
‘Congress’=’#0000FF’,
‘DMK’=’#00FA9A’,
‘TMC’=’#20B2AA’,
‘YSRC’=’#B8860B’,
‘Shiv Sena’=’#B22222',
‘JDU’=’#FF00FF’,
‘BJD’=’#6495ED’,
‘BSP’=’#ADFF2F’,
‘TRS’=’#FF7F50',
‘LJP’=’#CD5C5C’,
‘NCP’=’#F08080',
‘Samajwadi Party’=’#E9967A’,
‘Independent’=’#FA8072',
‘CPM’=’#FF0000',
‘IUML’=’#FF4500',
‘National Conference’=’#800000',
‘TDP’=’#9ACD32',
‘Apna Dal S’=’#FFD700',
‘CPI’=’#FF0000',
‘Shiromani Akali Dal’=’#000080',
‘AAP’=’#EEE8AA’,
‘AIADMK’=’#E81B23',
‘AIMIM’=’#000000',
‘AIUDF’=’#000000',
‘AJSU Party’=’#FF0000',
‘JDS’=’#00FF00',
‘JMM’=’#20B2AA’,
‘Kerala Congress (M)’=’#FFFF00',
‘MIM’=’#00FFFF’,
‘Mizo National Front’=’#FF00FF’,
‘NDPP’=’#C0C0C0',
‘NPF’=’#808080',
‘NPP’=’#800000',
‘RLP’=’#808000',
‘RSP’=’#008000',
‘SKM’=’#800080',
‘VCK’=’#008080' )) +
theme(legend.position = “bottom”) +
geom_highlight_government(government == 1, shape = 25) +
draw_totalseats(n = 543, type = ‘semicircle’) +
draw_majoritythreshold(
n = 272,
label = TRUE,
type = ‘semicircle’
) +
theme(plot.title = element_text(hjust = 0.5))

And this is our final parliament chart:

#Display the plot
ind
India Parliament Chart General Elections 2019

Scatter Plot of voting % over the years and Animation chart of top two parties

We will be needing ‘gganimate’ and ‘gifsky’ packages to make an animation chart. Let us load the libraries.

#This code displays animation chart for vote % over the years for parties two largest parties Congress and BJP
#Data source given below
##devtools::install_github(‘thomasp85/gganimate’) load latest gganimate packages
#load the packages
library(ggplot2)
library(readr)
library(dplyr)
library(tidyr)
library(gganimate)
library(gifski) #part of gganimate

Load the data.

#get the dataResults <- read.csv(‘D:/Harish/R practice projects/india/election/Data/Voting_Per_Over_The_Years_BJP_INC.csv’, stringsAsFactors = F, na.strings=c(“”,”NA”))#EDA
typeof(Results)
head(Results)
sum(is.na(Results))
str(Results)
nrow(Results)
> head(Results)
Year Party Seats Votes_PERCEN
1 2019 INC 52 19.49
2 2014 INC 44 19.60
3 2009 INC 206 28.60
4 2004 INC 145 26.50
5 1999 INC 114 28.30
6 1998 INC 141 25.80

Scatter Plot

Draw the scatter plot. Look how BJP emerged after year 1980.

#1 Scatter Plot
ind_1 <- ggplot(data = Results, aes(x = Year, y = Votes_PERCEN, colour = Party)) +
geom_line() +
scale_color_manual(values=c(‘BJP’=’#FF8C00',
‘INC’=’#0000FF’)) +
labs(subtitle=”Indian Elections Voting % Share Over the Years”,
y=”Voting %”,
x=”Party”,
title=”Scatterplot”,
caption = “SOURCE: oneindia.com, indiatoday.in, eci.gov.in, indiavotes.com & wiki”)
ind_1
Scatter plot of vote % between BJP and Congress over the years

Animation chart

Let us draw an animation chart with below code.

#animation chart with geom points
theme_set(theme_bw())
#Result_Sel_BJP <- Results %>% filter(Results$Party == ‘BJP’ )
ind_2 <- ggplot(Results, aes(Year, Votes_PERCEN, size = Votes_PERCEN, frame = Year, colour = Party)) +
geom_point() + transition_time(Year) +
labs(title = “Year : {frame_time}”) + shadow_wake(wake_length = 0.1, alpha = FALSE) +
labs(subtitle=”BJP & COngress % Share Over the Years”,
caption = “SOURCE: oneindia.com, indiatoday.in, eci.gov.in, indiavotes.com & wiki”)

ind_2
#saving the animation chart
anim_save(“animation_chart_with_geom_points.gif”)

Here is the animation chart with gganimation package. Look how points are moving as the year changes.

Animation chart of Vote % between BJP and Congress over the years

You can use above code to draw such charts for any election. For full R code of various charts, please download the code and charts from my github page here.

With this I am finishing my article. Thank for reading full article. Will meet soon with a new article.

Feel free to give your comments or mail me at harnagpal@gmail.com.

Have a look at my other articles on Medium.com

See my data science maths art here.

References

https://www.oneindia.com/

--

--

Harish Nagpal
Analytics Vidhya

An IT professional, passionate about art in all forms — data, nature, paintings and visual art. Linkedln — https://www.linkedin.com/in/harish-nagpal-8696529/