# Eerste Kamer simulations ------------------------------------------------
# Tom Louwerse, 2019
setwd("../..")

# Load data ---------------------------------------------------------------

# Load output from Peilingwijzer
load("Last/outputs.RData")
load("Last/sourcedata.RData")

# Read libraries
library(rjags)
## Loading required package: coda
## Linked to JAGS 4.2.0
## Loaded modules: basemod,bugs
library(colorspace)
library(doSNOW)
## Loading required package: foreach
## Loading required package: iterators
## Loading required package: snow
library(car)
## Loading required package: carData
library(xlsx)
library(Hmisc)
## Loading required package: lattice
## Loading required package: survival
## Warning: package 'survival' was built under R version 3.5.1
## Loading required package: Formula
## Loading required package: ggplot2
## Warning: package 'ggplot2' was built under R version 3.5.1
## 
## Attaching package: 'Hmisc'
## The following objects are masked from 'package:base':
## 
##     format.pval, units
library(rjson)
library(dplyr)
## Warning: package 'dplyr' was built under R version 3.5.1
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:Hmisc':
## 
##     src, summarize
## The following object is masked from 'package:car':
## 
##     recode
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(SDMTools)
library(truncnorm)
## Warning: package 'truncnorm' was built under R version 3.5.1
# Source code
source("Code/printgraph.R")
source("Code/makeGraph.R")
source("Code/seatDistribution.R")
source("Code/runModels.R")
source("Code/resultParty.R")
source("Code/resultPartyDate.R")
source("Code/houseEffects.R")
## Loading required package: stringr
source("Code/extractnames.R")
source("Code/getClosestPoll.R")
source("Code/compareTable.R")
source("Code/compareDates.R")

# Set some parameters -----------------------------------------------------
electionDate <- as.Date("2017-03-15")
electionDay <- julian(as.Date("2017-03-15"),origin=as.Date("2010-01-01"))
lastdate <- max(sourcedata[[1]]$dat$date)

partylist <- sapply(sourcedata, function(q) q$partyname)
partyabbr <- sapply(sourcedata, function(q) q$partyabbr)
n.parties <- length(partylist)
partycolours <- c(sapply(sourcedata, function(q) q$partycolour), "#7f8085")
partycolours.bright <- hex(mixcolor(0.4, hex2RGB(partycolours), RGB(1,1,1)))
partycolours.brightest <- hex(mixcolor(0.7, hex2RGB(partycolours), RGB(1,1,1)))

plotcolours <- partycolours
lastdate <- max(sourcedata[[1]]$dat$date)


# Read ratio data ---------------------------------------------------------
ratio_data <- rio::import("projects/2019 EK/Ratio_TK_EK_2019.xlsx")
ratios <- ratio_data %>%
  select(PW_Ratio_EK_2011, PW_Ratio_2011, PW_Ratio_EK_2015, PW_Ratio_2015)


ratio_source <- left_join(data.frame(party=partylist), data.frame(party=ratio_data$party,ratios))
## Joining, by = "party"
ratio_weights = c(1,1,1,1) / 4 * ncol(ratios)
ratio <- apply(ratios, 1, function(q) weighted.mean(q, ratio_weights,na.rm=TRUE))
ratio_min <- apply(ratios, 1, function(q) min(q, na.rm=TRUE))
ratio_max <- apply(ratios, 1, function(q) max(q, na.rm=TRUE))
ratio_sd <- apply(ratios, 1, function(q) wt.sd(q, ratio_weights))


# Show data used
ratio_df <- data.frame(party=ratio_data$party, Ratio=ratio, Ratio_SD=ratio_sd, 
           Ratio_Min=ratio_min, Ratio_Max=ratio_max)

# Add OSF ratio
ratio_df <- left_join(data.frame(party=partylist), ratio_df) %>%
  rbind(data.frame(party="OSF", Ratio=1,Ratio_SD=0.05, Ratio_Min=0.90, Ratio_Max=1.1))
## Joining, by = "party"
ratios <- ratio_source[,-1]

#Display ratios as used in nowcast model
ratio_df
##     party     Ratio   Ratio_SD Ratio_Min Ratio_Max
## 1     VVD 0.9664993 0.05860477 0.8960212 1.0373404
## 2     PVV 0.7802082 0.01878366 0.7540041 0.7952925
## 3     CDA 1.2365208 0.08232037 1.1608209 1.3281802
## 4     D66 0.9058463 0.06240140 0.8452586 0.9922335
## 5      GL 1.1616014 0.03282734 1.1303654 1.2066960
## 6      SP 0.9243595 0.03521430 0.8866963 0.9618485
## 7    PvdA 1.0484233 0.09464969 0.9518941 1.1526222
## 8      CU 0.9936987 0.11286002 0.8889668 1.1407023
## 9    PvdD 1.0592104 0.20363731 0.7625481 1.2119175
## 10 50PLUS 1.0383855 0.28086409 0.7850632 1.4035978
## 11    SGP 1.0964924 0.16729256 0.9443960 1.3113269
## 12   Denk 0.9000000 0.23094011 0.7000000 1.1000000
## 13    FvD 0.9000000 0.23094011 0.7000000 1.1000000
## 14    OSF 1.0000000 0.05000000 0.9000000 1.1000000
# Plot ratios -------------------------------------------------------------
ratioColours <- c("black", "grey","darkred","pink") #"orange","darkblue"
ratioPch <- c(15,16,17,18,19)  #23,25

windows(8,6)
par(mar=c(5.1,6.1,4.1,8.1),xpd=FALSE)
plot(ratios[1:11,1], 1:11, type="n", axes=F, xlim=c(0.6,1.5),
     ylab="", xlab="")
title("Verhouding tussen Peilingwijzer Tweede Kamer en \nuitslag Provinciale Staten/Eerste Kamer")
abline(h=1:11, col="grey80")
abline(v=1, lty=2, col="grey60")
for(i in 1:11)
 points(ratios[i,1:4], rep(i, ncol(ratios)),
        col=ratioColours, pch=ratioPch,bg=ratioColours)
axis(1, at=seq(0.5,1.5,.1), col="grey60")
axis(2, at=1:11, labels=partylist[1:11], las=1, col="grey60")

ratioNames <- c("2011 (EK)","2011 (PS)", "2015 (EK)","2015 (PS)")

par(xpd=TRUE)
legend("bottomright", inset=c(-0.30,0), legend=ratioNames, col=ratioColours,lwd=NA,pch=ratioPch,ncol=1, cex=.8, box.col="grey50", text.col="grey60", pt.bg=ratioColours)
text(.55,-1, "Scoort slechter bij\nPS/EK", pos=4)
text(1.55,-1, "Scoort beter bij\n PS/EK", pos=2)

 savePlot("projects/2019 EK/Ratio peilingen PS-TK", type="pdf")
 savePlot("projects/2019 EK/Ratio peilingen PS-TK", type="png")
 graphics.off()


# Calculate EK simulations based on TK poll -------------------------------

# Get data from Peilingwijzer output
alldata <- foreach(i=1:length(outputs), .combine=cbind) %do% {
  alphas <- outputs[[i]][,grep("^alpha",dimnames(outputs[[i]][[1]])[[2]])]
  unlist(alphas[,ncol(alphas[[1]])])
}

# Function to calculate EK score based on TK polls, using ratios
calcEK <- function(x) {
  # Add OSF score ~ uniform distribution 1%-2%
  x <- c(x, runif(1, 0.01,.02))
  names(x) <- c(partylist, "OSF")
  
  # # Sample ratio from truncated normal distribution
  # ratio_sample <- rtruncnorm(length(ratio_df$Ratio), 
  #                            a=ratio_df$Ratio_Min,
  #                            b=ratio_df$Ratio_Max,
  #                            ratio_df$Ratio, ratio_df$Ratio_SD)
  # 
  
  # Sample ratio from truncated normal distribution
  # Because we have no information on ratios from current polls yet, 
  # used wider range for truncation (i.e. more uncertainty)
  ratio_sample <- rtruncnorm(length(ratio_df$Ratio), 
                             a=0,
                             b=2,
                             ratio_df$Ratio, ratio_df$Ratio_SD)
  
  # Calculate original data times ratio and sum to 1
  return(x * ratio_sample/sum(x * ratio_sample))
}

# Get percentage scores for EK
results.perc <- foreach(i = 1:nrow(alldata), .combine=rbind) %do% calcEK(alldata[i,])

# Calculate seats for EK
results <- foreach(i = 1:nrow(results.perc), .combine=rbind) %do% {
  dhondt(results.perc[i,], n.seats=75)  
}

save(results.perc, results, file="projects/2019 EK/Results simulation.RData")

# Display some outputs ----------------------------------------------------
print("Kans op aantal zetels per partij")
## [1] "Kans op aantal zetels per partij"
apply(results, 2, function(q) table(q) / 2500)
## $VVD
## q
##     11     12     13     14     15     16     17     18 
## 0.0020 0.0232 0.2024 0.4124 0.2892 0.0668 0.0036 0.0004 
## 
## $PVV
## q
##      6      7      8 
## 0.2392 0.7460 0.0148 
## 
## $CDA
## q
##      6      7      8      9     10     11 
## 0.0012 0.0856 0.5140 0.3616 0.0364 0.0012 
## 
## $D66
## q
##      4      5      6      7 
## 0.0180 0.5764 0.3980 0.0076 
## 
## $GL
## q
##      9     10     11     12     13 
## 0.0024 0.2272 0.6552 0.1144 0.0008 
## 
## $SP
## q
##      5      6      7 
## 0.1844 0.7848 0.0308 
## 
## $PvdA
## q
##      3      4      5      6      7 
## 0.0004 0.0644 0.5792 0.3340 0.0220 
## 
## $CU
## q
##      2      3      4      5      6 
## 0.0316 0.6384 0.3244 0.0052 0.0004 
## 
## $PvdD
## q
##      0      1      2      3      4      5      6 
## 0.0004 0.0044 0.0960 0.4492 0.3712 0.0756 0.0032 
## 
## $`50PLUS`
## q
##      0      1      2      3      4      5 
## 0.0032 0.1196 0.4344 0.3604 0.0784 0.0040 
## 
## $SGP
## q
##      0      1      2      3 
## 0.0012 0.5180 0.4800 0.0008 
## 
## $Denk
## q
##      0      1      2      3 
## 0.0216 0.3912 0.5328 0.0544 
## 
## $FvD
## q
##      0      1      2      3      4      5      6      7      8      9 
## 0.0004 0.0032 0.0276 0.0772 0.1948 0.2752 0.2380 0.1320 0.0420 0.0092 
##     10 
## 0.0004 
## 
## $OSF
## q
##      0      1 
## 0.1984 0.8016
print("Mediaan aantal zetels + CI per partij")
## [1] "Mediaan aantal zetels + CI per partij"
apply(results, 2, function(q) c(median(q), quantile(q, .025), quantile(q, .975)))
##          VVD PVV CDA D66 GL SP PvdA CU PvdD 50PLUS SGP Denk FvD OSF
##       14.000   7   8   5 11  6    5  3    3      2   1    2   5   1
## 2.5%  12.475   6   7   5 10  5    4  2    2      1   1    1   2   0
## 97.5% 16.000   7  10   6 12  7    6  4    5      4   2    3   8   1
print("Percentage + CI per partij")
## [1] "Percentage + CI per partij"
round(apply(results.perc, 2, function(q) c(mean(q), quantile(q, .025), quantile(q, .975)))*100, 1)
##        VVD PVV  CDA D66   GL  SP PvdA  CU PvdD 50PLUS SGP Denk  FvD OSF
##       17.9 8.8 10.8 7.2 13.9 7.7  7.1 4.7  4.8    3.5 2.4  2.6  7.0 1.5
## 2.5%  15.9 8.1  9.3 6.2 12.8 6.9  5.8 3.6  3.1    1.7 1.7  1.3  3.5 1.0
## 97.5% 19.9 9.6 12.3 8.3 15.1 8.6  8.5 5.7  6.6    5.4 3.2  3.9 10.4 2.0
print("Aantal zetels bij gemiddeld percentage")
## [1] "Aantal zetels bij gemiddeld percentage"
dhondt(colMeans(results.perc), n.seats=75)
##    VVD    PVV    CDA    D66     GL     SP   PvdA     CU   PvdD 50PLUS 
##     14      7      8      6     11      6      5      3      3      2 
##    SGP   Denk    FvD    OSF 
##      2      2      5      1
# Largest parties
table(colnames(results)[apply(results, 1, which.max)]) / nrow(results)
## 
##     GL    VVD 
## 0.0004 0.9996
# Get coalition seats
coa_rowsums <- data.frame(results) %>%
  select(VVD,CDA,D66,CU) %>%
  rowSums

print("Mediaan zetelaantal en CI Coalitie")
## [1] "Mediaan zetelaantal en CI Coalitie"
c(median(coa_rowsums), quantile(coa_rowsums,.025), quantile(coa_rowsums, .975))
##        2.5% 97.5% 
##    31    29    34
print("Verdeling zetelaantallen Coalitie")
## [1] "Verdeling zetelaantallen Coalitie"
table(coa_rowsums) / length(coa_rowsums) * 100
## coa_rowsums
##    27    28    29    30    31    32    33    34    35    37 
##  0.08  0.96  6.80 19.72 32.08 25.04 11.96  2.96  0.36  0.04
print("Kans op meerderheid Coalitie")
## [1] "Kans op meerderheid Coalitie"
table(coa_rowsums > 37) / length(coa_rowsums) * 100
## 
## FALSE 
##   100
# Plot graph (parties) ----------------------------------------------------

graphSeats = function(x,...) {
  barplot(x/sum(x)*100,...)
}

windows(6.7,6.7)
par(mfrow=c(5,3),bg="transparent",mar=c(2.5,2.5,2.5,2.5))

v = apply(results, 2, function(x) table(x))
for(i in 1:length(v)) {
  uit = graphSeats(v[[i]], 
                   plot=T,axes=F,col="transparent",
                   border=NA, names.arg=F)
  abline(h=pretty(c(0,as.numeric(v[[i]]/sum(v[[i]]))) * 100,n.min=3),
         col="grey80")
  abline(h=c(0),col="grey40",lwd=1)
  colbars = rep(partycolours[i], length(names(v[[i]])))
  # Plot bars again to get on top of help lines
  graphSeats(v[[i]],main=names(v)[i],
             col=colbars, axisnames=FALSE,
             fg="grey60",border=NA, 
             col.main="grey50",add=TRUE,axes=FALSE)
  
  #col.axis="grey60",
  axis(2,at=pretty(c(0,as.numeric(v[[i]]/sum(v[[i]]))) * 100,n.min=3),
        labels=paste(pretty(c(0,as.numeric(v[[i]]/sum(v[[i]]))) * 100,n.min=3),
                     "%",sep=""),
       col.axis="grey60",col="grey80",tick=FALSE)
  axis(1,at=uit, labels=as.integer(names(v[[i]])), tick=FALSE, 
       col.axis="grey60", cex=.9)
} 
par(xpd=TRUE)
plot(c(0,1),c(0,1),type="n", axes=FALSE)
text(0,0.3, "Nowcast Eerste Kamer \nobv Peilingwijzer\nTom Louwerse,\nUniversiteit Leiden", cex=1, pos=4, col="grey")

savePlot("projects/2019 EK/Zetelaantallen Partijen", type="pdf")
savePlot("projects/2019 EK/Zetelaantallen Partijen", type="png")
graphics.off()

# Graph coalition + C3 ----------------------------------------------------

windows(6.2,6.2)
par(mfrow=c(1,1),bg="transparent",mar=c(3,3,3,3))

# Get table of outcomes for coalition parties combined
coac3 <- data.frame(results) %>%
  select(VVD,CDA,D66,CU) %>%
  rowSums %>%
  table

uit = graphSeats(coac3, plot=T,axes=F,
                 col="transparent",border=NA, names.arg=F,
                 xlab="Zetels", ylab="% van de simulaties", 
                 col.lab="grey80")
abline(h=pretty(coac3/sum(coac3) * 100,3),col="grey80")
abline(h=c(0),col="grey40",lwd=1)
colbars = c(rep("grey70",length(which(as.numeric(names(coac3))<38))), 
            rep("grey45", length(which(as.numeric(names(coac3))>37))))
graphSeats(coac3,main="Zetels Coalitie",
           col=colbars,col.axis="grey60",fg="grey60",border=NA, 
           col.main="grey50",add=TRUE,axes=F)
axis(2,at=pretty(coac3/sum(coac3) * 100,3),
     col.axis="grey60",col="grey80",tick=FALSE)

savePlot("projects/2019 EK/Zetelaantallen Coalitie", type="pdf")
savePlot("projects/2019 EK/Zetelaantallen Coalitie", type="png")
graphics.off()


# Graph Peilingwijzer TK - Percentages EK ---------------------------------

windows(7,7)
tk <- colMeans(alldata)
ek <- colMeans(results.perc)
ek <- ek[-14] # Remove OSF, not in TK data

plot(tk, ek, pch=16, xlim=c(0,.2), ylim=c(0,.2),
     xlab="Tweede Kamer (Peilingwijzer)", ylab="Eerste Kamer (Doorrekening)")
abline(a=0,b=1, lty=2, col="grey")
text(tk, ek, labels=names(ek), pos=3)

savePlot("projects/2019 EK/Vergelijking TK-EK", type="pdf")
savePlot("projects/2019 EK/Vergelijking TK-EK", type="png")
graphics.off()


# Met error

windows(7,7)
plot(tk, ek, pch=16, xlim=c(0,.2), ylim=c(0,.2), type="n",
     xlab="Tweede Kamer (Peilingwijzer)", ylab="Eerste Kamer (Doorrekening)")

for(i in 1:nrow(alldata)) {
  tk <- alldata[i,]
  ek <- results.perc[i,]
  ek <- ek[-14] # Remove OSF, not in TK data
  points(tk,ek,  col=partycolours.bright, pch=16, cex=.2)
}

tk <- colMeans(alldata)
ek <- colMeans(results.perc)
ek <- ek[-14] # Remove OSF, not in TK data
points(tk,ek,  col=partycolours, pch=16, cex=2)

abline(a=0,b=1, lty=2, col="grey", lwd=2)
text(tk, ek, labels=names(ek))