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")
<- mp_maindataset(version = "MPDS2018a")
mpds ## 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)
<- read_csv("http://www.parlgov.org/static/data/development-utf-8/view_cabinet.csv")
pg_cabinets 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.
<- read_csv("http://www.parlgov.org/static/data/development-utf-8/view_party.csv")
pg_parties 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.
<- filter(mpds, countryname == "Germany" & date > 196000)
mpds_germany <- filter(pg_cabinets, country_name == "Germany" & election_date > "1960-01-01")
pg_cabinets_germany <- filter(pg_parties, country_name == "Germany") pg_parties_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_parties_germany %>%
pg_mpds_link_table 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 %>% select(-party_name)
pg_mpds_link_table
<- left_join(pg_cabinets_germany, pg_mpds_link_table, by = "party_id") %>%
pg_cabinets_with_cmp_ids 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.
<- mpds_germany %>%
cabinets_mpds 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)