Exercises for Chapter 7
For the exercises, we need again the datasets used in Chapter 7 of the book. You can import and prepare these datasets using the code presented in the chapter.
The Polity IV dataset:
library(readxl)
polity <- read_excel(file.path("ch07", "polity.xls"))
The WID:
library(tidyverse)
library(countrycode)
wid <- read_csv(file.path("ch07", "inequality.csv"), na = "")
wid <- wid %>% select(country, year, value)
wid <- wid %>% rename(p90p100 = value)
wid <- wid %>% mutate(ccode = countrycode(country, "iso2c", "cown"))
wid <- wid %>% mutate(ccode = ifelse(country == "RS", 345, ccode))
Exercise 1: Creating New Variables and Temporal Lags
Sometimes, a binary categorization of regimes into autocracies and democracies may be too simple. The Polity project proposes an alternative classification of regimes as “autocracies” (-10 to -6), “anocracies” (-5 to +5 and three special values: -66, -77 and -88), and “democracies” (+6 to +10). Note that this categorization is based on the polity variable in the dataset, not the polity2 variable. Add a new variable regimetype to the dataset that implements this categorization. Use numeric codes for the regime types (0 for autocracies, 1 for anocracies, and 2 for democracies). The case_when() function is useful for this. Next, add a one-year lag of this variable to the data. Which cases are there where a country moved from an autocracy straight to a democratic system, skipping the anocracy category?
Solution
We first create a new variable with the three regime categories:
polity <- polity %>%
mutate(regimetype = case_when(
polity >= -10 & polity <= -6 ~ 0,
polity > +-5 & polity <= 5 ~ 1,
polity < -10 ~ 1,
TRUE ~ 2
))
Using the lag() function presented in the chapter, we lag this variable by one year:
polity <- polity %>%
group_by(ccode) %>%
mutate(regimetype_lag = lag(regimetype, order_by = year)) %>%
ungroup()
Finally, we filter out those cases where there was a transition directly from category 0 (autocracies) to category 2 (democracies):
polity %>% filter(regimetype == 2 & regimetype_lag == 0)
## # A tibble: 49 × 38
## cyear ccode scode country year flag fragment democ autoc polity polity2
## <dbl> <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 402018 40 CUB Cuba 2018 1 0 1 6 -5 -5
## 2 411990 41 HAI Haiti 1990 0 NA 7 0 7 7
## 3 411994 41 HAI Haiti 1994 0 NA 7 0 7 7
## 4 901958 90 GUA Guatemala 1958 0 NA 0 5 -5 -5
## 5 921956 92 SAL El Salva… 1956 0 NA 0 5 -5 -5
## 6 951982 95 PAN Panama 1982 0 NA 0 5 -5 -5
## 7 951989 95 PAN Panama 1989 0 NA 8 0 8 8
## 8 1011937 101 VEN Venezuela 1937 0 NA 0 5 -5 -5
## 9 1101992 110 GUY Guyana 1992 0 NA 6 0 6 6
## 10 1451982 145 BOL Bolivia 1982 0 NA 8 0 8 8
## # ℹ 39 more rows
## # ℹ 27 more variables: durable <dbl>, xrreg <dbl>, xrcomp <dbl>, xropen <dbl>,
## # xconst <dbl>, parreg <dbl>, parcomp <dbl>, exrec <dbl>, exconst <dbl>,
## # polcomp <dbl>, prior <dbl>, emonth <dbl>, eday <dbl>, eyear <dbl>,
## # eprec <dbl>, interim <dbl>, bmonth <dbl>, bday <dbl>, byear <dbl>,
## # bprec <dbl>, post <dbl>, change <dbl>, d4 <dbl>, sf <dbl>, regtrans <dbl>,
## # regimetype <dbl>, regimetype_lag <dbl>
Exercise 2: Grouping and Aggregation
Suppose we want to select those countries from the Polity dataset that were either democracies (polity2 >= 6) or non-democracies (polity2 < 6) over the entire observation period. How can you do this in a single tidyverse statement? Hint: use a simple grouping/aggregation procedure. Make sure you exclude country-years for which the polity2 is missing.
Solution
We group the data by country code and compute the minimum and the maximum of the polity2 score across all observations per country. The countries we are interested in are those that never reach the threshold of 6 (i.e. where the maximum is less than 6), and those that never go below 6 (i.e. where the minimum is 6 or higher).
polity %>%
group_by(scode) %>%
summarize(minpolity2 = min(polity2, na.rm = T), maxpolity2 = max(polity2, na.rm = T)) %>%
filter(minpolity2 >= 6 | maxpolity2 < 6)
## # A tibble: 88 × 3
## scode minpolity2 maxpolity2
## <chr> <dbl> <dbl>
## 1 AFG -10 0
## 2 ALG -9 2
## 3 ANG -7 0
## 4 AUL 10 10
## 5 AZE -7 1
## 6 BAD -7 -4
## 7 BAH -10 -5
## 8 BAV -10 -7
## 9 BOS 0 0
## 10 BOT 6 8
## # ℹ 78 more rows
Exercise 3: Joins with More Complex Join Conditions
A different way to study the evolution of inequality over time pattern is to compute in which year the different countries attained their maximum level of inequality. First, for each country, compute its maximum inequality according to the WID. Store these values in a separate table wid_max. Second, determine the year in which each country reached this maximum level. You can do this by joining wid_max and the original WID. What attributes should you base your join on? Consult the documentation to find out how to specify more complex join conditions. What potential problem do you see in the data? How would you solve it?
Solution
We compute a new dataset with the maximum value of inequality for each country.
wid_max <- wid %>%
group_by(ccode) %>%
summarize(maxineq = max(p90p100))
The original dataset can now be joined with the new one. We want to match those observations from wid where the country codes match and where the level of inequality matches the maximum.
wid_max <- wid_max %>% inner_join(wid, by = c("ccode" = "ccode", "maxineq" = "p90p100"))
If you look closely at wid_max, you can see that several countries show up more than once. For example, countries such as Yemen have a constant level of inequality over many years, which is why they reach their maximum in all these years. One solution is to simply remove those countries where the year of the maximum level of inequality is not uniquely defined.
wid_count <- wid_max %>%
group_by(country) %>%
summarize(count = n())
wid_max <- wid_max %>% inner_join(wid_count)
## Joining with `by = join_by(country)`
wid_max %>% filter(count == 1)
## # A tibble: 76 × 5
## ccode maxineq country year count
## <dbl> <dbl> <chr> <dbl> <int>
## 1 2 0.480 US 1934 1
## 2 140 0.565 BR 2011 1
## 3 155 0.557 CL 2007 1
## 4 200 0.362 GB 2007 1
## 5 205 0.375 IE 2014 1
## 6 210 0.286 NL 2015 1
## 7 211 0.292 BE 1994 1
## 8 212 0.320 LU 2007 1
## 9 220 0.517 FR 1910 1
## 10 225 0.322 CH 2016 1
## # ℹ 66 more rows
Exercise 4: Self-joining a Dataset
In this exercise, we want to identify those countries with the most extreme fluctuations in inequality over the entire observation period, in other words, where the difference between the maximum and the minimum level of inequality is particularly large. We want measure these fluctuations to occur with arbitrary periods of five years. The easiest way to do this is to use the Cartesian Product method, using the same table twice. Create pairs of observations for the same country, which are a maximum of five years apart. We can then sort these pairs in decreasing order to get the result we want. Hint: you will need to consult the documentation for the dplyr join function to find out how to create a Cartesian Product (which in the documentation is referred to as a “cross-join”). Think about which of the combinations of rows from the two tables do you need to keep!
Solution
We join the table with itself. To get all combinations of rows, we need to set by=character(). Note that because the table enters the join twice, the columns are relabeled as *.x and *.y, because column names must be unique in the result. From the result, we retain those combinations where the refer to the same country (country.x==country.y) and where the first year is smaller than the second (such that the observations are in the correct temporal order). Also, we want the paired observations to be a maximum of five years apart (year.y-year.x <= 5).
wid_pairs <- wid %>%
inner_join(wid, by = character()) %>%
filter(country.x == country.y & year.x < year.y & year.y - year.x <= 5)
## Warning: Using `by = character()` to perform a cross join was deprecated in dplyr 1.1.0.
## ℹ Please use `cross_join()` instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
You may also note that this procedure is not very efficient, due to the huge number of combinations we get in the Cartesian Product. The great majority of these cases is irrelevant and later dropped in the filter statement. We will learn about more efficient ways to conduct these more complex joins when we work with relational databases in later chapters.
Next, we need to compute the difference in inequality between the two observations in each pair. We use the abs() function, since we don’t care about the direction of change.
wid_pairs <- wid_pairs %>% mutate(ineqchange = abs(p90p100.x - p90p100.y))
Last, we output the pairs, sorted by ineqchange in decreasing order.
wid_pairs %>% arrange(desc(ineqchange))
## # A tibble: 15,220 × 9
## country.x year.x p90p100.x ccode.x country.y year.y p90p100.y ccode.y
## <chr> <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 RU 1991 0.246 365 RU 1996 0.483 365
## 2 MW 1998 0.757 553 MW 2003 0.548 553
## 3 MW 1999 0.715 553 MW 2004 0.507 553
## 4 MW 1997 0.799 553 MW 2002 0.590 553
## 5 RU 1990 0.236 365 RU 1995 0.424 365
## 6 RU 1991 0.246 365 RU 1995 0.424 365
## 7 MR 1993 0.620 435 MR 1995 0.444 435
## 8 MR 1993 0.620 435 MR 1996 0.446 435
## 9 MR 1993 0.620 435 MR 1997 0.447 435
## 10 MR 1993 0.620 435 MR 1998 0.448 435
## # ℹ 15,210 more rows
## # ℹ 1 more variable: ineqchange <dbl>