Adding Parties’ Government/Opposition Status to the Manifesto Project Dataset using ParlGov Data

Nicolas Merz & Fabio Ellger

2 August 2018 (slightly updated 14 June 2021)

In this tutorial, we will show how to merge the Manifesto Project Dataset with data on cabinet compositions from parlgov.org. We assume that you have already read the Short primer on the Manifesto Project and its methodology and First steps with manifestoR. Moreover, you should be familiar with the %>% operator and the dplyr package and grammar.

For detailed instructions on how to merge and harmonise the Manifesto Project Dataset and the ParlGov Dataset, have a look at the tutorial Government Positions from Party-Level Data by Dimiter Toshkov and/or the tutorial Merging Comparative Manifesto Project and ParlGov Data by Hauke Licht.

ParlGov.org - a data source for parties, cabinets and elections

Along with our policy-codings, our dataset encompasses a number of useful metadata, such as the voteshare (pervote), partyname and -abbreviation, or codes that identify eu- and oecd-membership. However, a majority of research questions demand for more information and a broader dataset. Thus, combining the Manifesto Project Dataset with other datasets is often necessary to answer many research questions. In this brief tutorial, we will show how our data can be expanded by merging it with the popular database ParlGov (Döring & Manow 2018). Parlgov provides information on parties, cabinets and elections for 37 countries (EU and OECD). This can be useful if for example one would like to distinguish strategies of opposiiton and government parties, analyze whether some parties or strategies are associated with gaining or loosing office, or when calculating the position of whole cabinets (in contrast to party positions).

Downloading data

We first download the Manifesto Project Dataset using manifestoR (see the tutorial First steps with manifestoR for a more detailed explanation of this step): we load manifestoR, set the apikey and download the current version of the Manifesto Project Dataset.

library(manifestoR) # to access the Manifesto Project Dataset
library(ggplot2) # for plots
library(dplyr) # for data wrangling
library(tidyr) # for data wrangling, too
library(lubridate) # for handling date variables


# Loading the Manifesto Project Dataset (Version 2018a)
mp_setapikey(key.file = "manifesto_apikey.txt")
mpds <- mp_maindataset(version = "MPDS2018a")
## Connecting to Manifesto Project DB API... corpus version: 2020-2

Parlgov provides three main table views of its database:

view_party - Party information and merge table for various external data sets on party positions.

view_cabinet - Cabinet and opposition parties in parliament with their seat strength at each instance of government formation. (main view)

view_election - Electoral results for national and EP elections.

For our task here, we use the party and cabinet data. For the goal of easy replication of this tutorial, we read the data directly from the parlgov website within R, but it might be a good idea to save the raw data on your computer, too. We use the read_csv function from the readr package. This slightly differs from read.csv because it has different default settings: it does not convert characters to factors by default, and it encodes in UTF-8. Moreover, it automatically detects dates as dates and returns a clean tibble instead of a “normal” data.frame.

# Loading information on cabinets and parties from ParlGov data
library(readr)
pg_cabinets <- read_csv("http://www.parlgov.org/static/data/development-utf-8/view_cabinet.csv")
pg_cabinets
## # A tibble: 12,173 x 19
##    country_name_sh… country_name election_date start_date cabinet_name caretaker
##    <chr>            <chr>        <date>        <date>     <chr>            <dbl>
##  1 AUS              Australia    1901-03-30    1901-03-30 Barton               1
##  2 AUS              Australia    1901-03-30    1901-03-30 Barton               1
##  3 AUS              Australia    1901-03-30    1901-03-30 Barton               1
##  4 AUS              Australia    1901-03-30    1901-03-30 Barton               1
##  5 AUS              Australia    1901-03-30    1901-03-30 Barton               1
##  6 AUS              Australia    1901-03-30    1903-09-24 Deakin I             0
##  7 AUS              Australia    1901-03-30    1903-09-24 Deakin I             0
##  8 AUS              Australia    1901-03-30    1903-09-24 Deakin I             0
##  9 AUS              Australia    1901-03-30    1903-09-24 Deakin I             0
## 10 AUS              Australia    1901-03-30    1903-09-24 Deakin I             0
## # … with 12,163 more rows, and 13 more variables: cabinet_party <dbl>,
## #   prime_minister <dbl>, seats <dbl>, election_seats_total <dbl>,
## #   party_name_short <chr>, party_name <chr>, party_name_english <chr>,
## #   left_right <dbl>, country_id <dbl>, election_id <dbl>, cabinet_id <dbl>,
## #   previous_cabinet_id <dbl>, party_id <dbl>

The cabinet composition data includes information on which parties within a country formed a cabinet. Rows are the most relevant parties within a country. election_date indicates the date of the last election. cabinet_name is the name of the cabinet (the prime minister + a Roman number), the variable cabinet_party indicates whether a party was part of a cabinet or not. For more information on the precise meaning and coding of the variables, see the parlgov website.

pg_parties <- read_csv("http://www.parlgov.org/static/data/development-utf-8/view_party.csv")
pg_parties
## # A tibble: 1,659 x 23
##    country_name_sho… country_name party_name_short party_name_engli… party_name 
##    <chr>             <chr>        <chr>            <chr>             <chr>      
##  1 AUS               Australia    ACP-V            Australian Count… Australian…
##  2 AUS               Australia    AD               Australian Democ… Australian…
##  3 AUS               Australia    AG               Australian Greens Australian…
##  4 AUS               Australia    ALP              Australian Labor… Australian…
##  5 AUS               Australia    AP               Australia Party   Australia …
##  6 AUS               Australia    C                Coalition         Coalition  
##  7 AUS               Australia    CDP              Christian Democr… Christian …
##  8 AUS               Australia    CLP              Commonwealth Lib… Commonweal…
##  9 AUS               Australia    CN-QLD           Country-National… Country-Na…
## 10 AUS               Australia    CPA              Communist Party … Communist …
## # … with 1,649 more rows, and 18 more variables: party_name_ascii <chr>,
## #   family_name_short <chr>, family_name <chr>, left_right <dbl>,
## #   state_market <dbl>, liberty_authority <dbl>, eu_anti_pro <dbl>, cmp <dbl>,
## #   euprofiler <dbl>, ees <dbl>, castles_mair <dbl>, huber_inglehart <dbl>,
## #   ray <dbl>, benoit_laver <dbl>, chess <dbl>, country_id <dbl>,
## #   party_id <dbl>, family_id <dbl>

Merging and working with the data

In the following, we will illustrate how to merge the Manifesto Project Data with parlgov data. For illustrative purposes, we will do this on German governments since 1950 only, but the shown procedure should work similarly for other countries.

Subsetting

We subset the the three data sources to electoral programs issued by German parties since 1960, German governments since 1960 and German parties.

mpds_germany <- filter(mpds, countryname == "Germany" & date > 196000)
pg_cabinets_germany <- filter(pg_cabinets, country_name == "Germany" & election_date > "1960-01-01")
pg_parties_germany <- filter(pg_parties, country_name == "Germany")

Merging

ParlGov data is easy to merge with the Manifesto Project Data because the party view tables contain the party identifier from the Manifesto Project (often called CMP party code). To be able to calculate government position based on the positions of electoral programs of parties that form a government, we first merge the parlgov party information with the cabinet information, so that the cabinet information also contains the party identifier.

We first create a simple link table from the parlgov party view that only includes the parlgov party id , the cmp variable (the Manifesto Project party id) and the party name.

pg_mpds_link_table <- pg_parties_germany %>%
  select(party_id, cmp, party_name) %>%
  mutate(cmp = ifelse(party_id == 255, 41113, cmp))

pg_mpds_link_table
## # A tibble: 57 x 3
##    party_id   cmp party_name                                    
##       <dbl> <dbl> <chr>                                         
##  1     2253    NA Alternative für Deutschland                   
##  2      255 41113 Bündnis 90 / Grüne – BürgerInnenbewegung      
##  3      772 41113 Bündnis 90 / Die Grünen                       
##  4     2701    NA Bayerischer Bauernbund                        
##  5     1720    NA Bund freier Bürger – Offensive für Deutschland
##  6     2707    NA Badischer Landbund                            
##  7     1131 41911 Bayernpartei                                  
##  8     2697    NA Bayerische Volkspartei                        
##  9     2703    NA Bauern- und Weingärtnerbund                   
## 10      808 41521 Christlich Demokratische Union                
## # … with 47 more rows

While this link tables from parlgov are relatively complete, they are sometimes not up-to-date. Here, we eg add the cmp party code for the Alternative für Deutschland yet.

pg_mpds_link_table <- pg_mpds_link_table %>%
  mutate(cmp = ifelse(party_name == "Alternative für Deutschland", 41953, cmp))

Moreover, parlgov sometimes treats parties slightly different than the Manifesto Project Dataset due to other coding criteria for political parties. For example the Manifesto Project treats the Left Party and the PDS as different parties with different ids. In contrast, parlgov codes them with the same party_id. In order to correctly merge them, we need to harmonize the coding in our dataset and treat them as the same party, too.

mpds_germany <- mpds_germany %>%
  mutate(
    party = ifelse(party %in% c(41222, 41223), 41221, party),
    party = ifelse(party %in% c(41111, 41112, 41113), 41113, party),
    partyabbrev = ifelse(party == 41113, "Greens", partyabbrev),
    partyabbrev = ifelse(party == 41221, "Left", partyabbrev)
  )

We then add the cmp ids to the cabinet information by left joining them to the cabinet data. For the sake of simplicity in this tutorial, we only keep the information for the first cabinet in each election term. Depending on the research question, one might rather take the last cabinet, or keep the information from all cabinets.

pg_mpds_link_table <- pg_mpds_link_table %>% select(-party_name)

pg_cabinets_with_cmp_ids <- left_join(pg_cabinets_germany, pg_mpds_link_table, by = "party_id") %>%
  select(cabinet_party, party_id, cmp, party_name, cabinet_name, cabinet_id, election_date, start_date, seats, election_seats_total) %>%
  # adding the cmp-codes to the parlgov cabinet data on germany
  group_by(election_date) %>%
  top_n(n = 1, wt = cabinet_id) %>%
  ungroup() # only keep information from first cabinet in each electoral term

In the next step, we slightly shorten the mpds dataset and keep only the party, date and the left-right positon (rile) and merge with the cabinet data.

cabinets_mpds <- mpds_germany %>%
  select(edate, party, partyabbrev, rile, pervote, absseat) %>%
  left_join(pg_cabinets_with_cmp_ids, by = c("party" = "cmp", "edate" = "election_date")) %>%
  filter(edate > "1960-01-01") %>%
  mutate(cabinet_party = ifelse(edate == "2013-09-27" & partyabbrev == "FDP", 0, cabinet_party)) %>%
  filter(!is.na(cabinet_party))

cabinets_mpds
## # A tibble: 66 x 14
##    edate      party partyabbrev    rile pervote absseat cabinet_party party_id
##    <date>     <dbl> <chr>         <dbl>   <dbl>   <dbl>         <dbl>    <dbl>
##  1 1961-09-17 41320 SPD          -2.91    36.2      190             0      558
##  2 1961-09-17 41420 FDP         -17.8     12.8       67             1      543
##  3 1961-09-17 41521 CDU/CSU       2.33    45.3      242             1     1727
##  4 1965-09-19 41320 SPD          -5.92    39.3      202             0      558
##  5 1965-09-19 41420 FDP           0.943    9.49      49             1      543
##  6 1965-09-19 41521 CDU/CSU      -1.6     47.6      245             1     1727
##  7 1969-09-28 41320 SPD         -10.4     42.7      224             1      558
##  8 1969-09-28 41420 FDP         -18.7      5.77      30             1      543
##  9 1969-09-28 41521 CDU/CSU      -5.08    46.1      242             0     1727
## 10 1972-11-19 41320 SPD         -14.4     45.8      230             1      558
## # … with 56 more rows, and 6 more variables: party_name <chr>,
## #   cabinet_name <chr>, cabinet_id <dbl>, start_date <date>, seats <dbl>,
## #   election_seats_total <dbl>

Plotting parties’ ideological movements

We have succesfully merged our info on party manifestos with data by parlgov on cabinet status. We plot parties’ ideological movements. The shapes provide information on the government/opposition status. A triangle marks when a party gained office at a focal election and marks when it became an opposition party.

ggplot(data = cabinets_mpds, aes(edate, rile), group = as.factor(partyabbrev)) +
  geom_line(aes(colour = as.factor(partyabbrev))) +
  geom_point(aes(shape = factor(cabinet_party, labels = c("Opposition", "Government")), colour = as.factor(partyabbrev)), size = 3) +
  labs(color = "Party", shape = "government status", y = "Left-Right-Positions", x = "Time")

References

Döring, Holger & Philip Manow (2018): Parliaments and governments database (ParlGov): Information on parties, elections and cabinets in modern democracies. Development version. Parlgov.org

Session Info

Tested with:

## ─ Session info ───────────────────────────────────────────────────────────────
##  setting value                       
##  version R version 4.0.3 (2020-10-10)
##  date    2021-06-15                  
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package     * version date       lib  source        
##  assertthat    0.2.0   2017-04-11 [NA] CRAN (R 4.0.3)
##  base64enc     0.1-3   2015-07-28 [NA] CRAN (R 4.0.2)
##  bookdown      0.22    2021-04-22 [NA] CRAN (R 4.0.2)
##  cli           1.1.0   2019-03-19 [NA] CRAN (R 4.0.3)
##  colorspace    1.3-2   2016-12-14 [NA] CRAN (R 4.0.3)
##  crayon        1.3.4   2017-09-16 [NA] CRAN (R 4.0.2)
##  curl          3.2     2018-03-28 [NA] CRAN (R 4.0.3)
##  digest        0.6.21  2019-09-20 [NA] CRAN (R 4.0.3)
##  dplyr       * 1.0.6   2021-05-05 [NA] CRAN (R 4.0.2)
##  DT            0.7     2019-06-11 [NA] CRAN (R 4.0.3)
##  ellipsis      0.3.2   2021-04-29 [NA] CRAN (R 4.0.3)
##  evaluate      0.14    2019-05-28 [NA] CRAN (R 4.0.1)
##  fansi         0.4.0   2018-10-05 [NA] CRAN (R 4.0.3)
##  farver        2.0.1   2019-11-13 [NA] CRAN (R 4.0.3)
##  foreign       0.8-70  2018-04-23 [NA] CRAN (R 4.0.3)
##  functional    0.6     2014-07-16 [NA] CRAN (R 4.0.2)
##  generics      0.0.2   2018-11-29 [NA] CRAN (R 4.0.2)
##  ggplot2     * 3.3.3   2020-12-30 [NA] CRAN (R 4.0.2)
##  glue          1.4.2   2020-08-27 [NA] CRAN (R 4.0.2)
##  gtable        0.2.0   2016-02-26 [NA] CRAN (R 4.0.3)
##  highr         0.6     2016-05-09 [NA] CRAN (R 4.0.3)
##  hms           0.4.2   2018-03-10 [NA] CRAN (R 4.0.3)
##  htmltools     0.4.0   2019-10-04 [NA] CRAN (R 4.0.3)
##  htmlwidgets   1.5.3   2020-12-10 [NA] CRAN (R 4.0.2)
##  httr          1.3.1   2017-08-20 [NA] CRAN (R 4.0.3)
##  jsonlite      1.6     2018-12-07 [NA] CRAN (R 4.0.3)
##  knitr         1.33    2021-04-24 [NA] CRAN (R 4.0.2)
##  labeling      0.3     2014-08-23 [NA] CRAN (R 4.0.3)
##  lattice       0.20-35 2017-03-25 [NA] CRAN (R 4.0.3)
##  lifecycle     1.0.0   2021-02-15 [NA] CRAN (R 4.0.2)
##  lubridate   * 1.7.10  2021-02-26 [NA] CRAN (R 4.0.2)
##  magrittr      2.0.1   2020-11-17 [NA] CRAN (R 4.0.2)
##  manifestoR  * 1.5.0   2020-11-29 [NA] CRAN (R 4.0.2)
##  mnormt        1.5-5   2016-10-15 [NA] CRAN (R 4.0.3)
##  munsell       0.5.0   2018-06-12 [NA] CRAN (R 4.0.2)
##  nlme          3.1-131 2017-02-06 [NA] CRAN (R 4.0.3)
##  NLP         * 0.1-9   2016-02-18 [NA] CRAN (R 4.0.3)
##  pillar        1.6.1   2021-05-16 [NA] CRAN (R 4.0.2)
##  pkgconfig     2.0.2   2018-08-16 [NA] CRAN (R 4.0.3)
##  psych         1.8.3.3 2018-03-30 [NA] CRAN (R 4.0.3)
##  purrr         0.3.2   2019-03-15 [NA] CRAN (R 4.0.3)
##  R6            2.2.2   2017-06-17 [NA] CRAN (R 4.0.3)
##  Rcpp          1.0.0   2018-11-07 [NA] CRAN (R 4.0.3)
##  readr       * 1.3.1   2018-12-21 [NA] CRAN (R 4.0.3)
##  rlang         0.4.10  2020-12-30 [NA] CRAN (R 4.0.2)
##  rmarkdown     2.8     2021-05-07 [NA] CRAN (R 4.0.2)
##  rmdformats    1.0.2   2021-04-19 [NA] CRAN (R 4.0.2)
##  scales        1.1.0   2019-11-18 [NA] CRAN (R 4.0.3)
##  sessioninfo   1.1.1   2018-11-05 [NA] CRAN (R 4.0.2)
##  slam          0.1-40  2016-12-01 [NA] CRAN (R 4.0.3)
##  stringi       1.1.7   2018-03-12 [NA] CRAN (R 4.0.3)
##  stringr       1.3.0   2018-02-19 [NA] CRAN (R 4.0.3)
##  tibble        3.1.2   2021-05-16 [NA] CRAN (R 4.0.2)
##  tidyr       * 0.8.0   2018-01-29 [NA] CRAN (R 4.0.3)
##  tidyselect    1.1.1   2021-04-30 [NA] CRAN (R 4.0.3)
##  tm          * 0.7-5   2018-07-29 [NA] CRAN (R 4.0.3)
##  utf8          1.1.3   2018-01-03 [NA] CRAN (R 4.0.3)
##  vctrs         0.3.8   2021-04-29 [NA] CRAN (R 4.0.3)
##  withr         2.1.2   2018-03-15 [NA] CRAN (R 4.0.3)
##  xfun          0.23    2021-05-15 [NA] CRAN (R 4.0.2)
##  xml2          1.2.0   2018-01-24 [NA] CRAN (R 4.0.3)
##  yaml          2.2.0   2018-07-25 [NA] CRAN (R 4.0.3)
##  zoo           1.7-13  2016-05-03 [NA] CRAN (R 4.0.3)