# Exploratory Data Analysis and Descriptive Statistics for Political Science Research in R Packages we will use:

``````library(tidyverse)      # of course
library(ggridges)       # density plots
library(GGally)         # correlation matrics
library(stargazer)      # tables
library(knitr)          # more tables stuff
library(kableExtra)     # more and more tables
library(ggrepel)        # spread out labels
library(ggstream)       # streamplots
library(bbplot)         # pretty themes
library(ggthemes)       # more pretty themes
library(ggside)         # stack plots side by side
library(forcats)        # reorder factor levels
``````

Before jumping into any inferentional statistical analysis, it is helpful for us to get to know our data. For me, that always means plotting and visualising the data and looking at the spread, the mean, distribution and outliers in the dataset.

Before we plot anything, a simple package that creates tables in the `stargazer` package. We can examine descriptive statistics of the variables in one table.

Click here to read this practically exhaustive cheat sheet for the stargazer package by Jake Russ. I refer to it at least once a week.

I want to summarise a few of the stats, so I write into the `summary.stat()` argument the number of observations, the mean, median and standard deviation.

The `kbl()` and `kable_classic()` will change the look of the table in R (or if you want to copy and paste the code into latex with the `type = "latex"` argument).

In HTML, they do not appear.

To find out more about the knitr kable tables, click here to read the cheatsheet by Hao Zhu.

Choose the variables you want, put them into a` data.frame` and feed them into the `stargazer()` function

``````stargazer(my_df_summary,
covariate.labels = c("Corruption index",
"Civil society strength",
'Rule of Law score',
"Physical Integerity Score",
"GDP growth"),
summary.stat = c("n", "mean", "median", "sd"),
type = "html") %>%
kbl() %>%
kable_classic(full_width = F, html_font = "Times", font_size = 25)``````
 Statistic N Mean Median St. Dev. Corruption index 179 0.477 0.519 0.304 Civil society strength 179 0.670 0.805 0.287 Rule of Law score 173 7.451 7.000 4.745 Physical Integerity Score 179 0.696 0.807 0.284 GDP growth 163 0.019 0.020 0.032

Next, we can create a barchart to look at the different levels of variables across categories. We can look at the different regime types (from complete autocracy to liberal democracy) across the six geographical regions in 2018 with the `geom_bar()`.

``````my_df %>%
filter(year == 2018) %>%
ggplot() +
geom_bar(aes(as.factor(region),
fill = as.factor(regime)),
color = "white", size = 2.5) -> my_barplot``````

And we can add more theme changes

``````my_barplot + bbplot::bbc_style() +
theme(legend.key.size = unit(2.5, 'cm'),
legend.text = element_text(size = 15),
text = element_text(size = 15)) +
scale_fill_manual(values = c("#9a031e","#00a896","#e36414","#0f4c5c")) +
scale_color_manual(values = c("#9a031e","#00a896","#e36414","#0f4c5c")) ``````

This type of graph also tells us that Sub-Saharan Africa has the highest number of countries and the Middle East and North African (MENA) has the fewest countries.

However, if we want to look at each group and their absolute percentages, we change one line: we add `geom_bar(position = "fill")`. For example we can see more clearly that over 50% of Post-Soviet countries are democracies ( orange = electoral and blue = liberal democracy) as of 2018.

We can also check out the density plot of democracy levels (as a numeric level) across the six regions in 2018.

With these types of graphs, we can examine characteristics of the variables, such as whether there is a large spread or normal distribution of democracy across each region.

``````my_df %>%
filter(year == 2018) %>%
ggplot(aes(x = democracy_score, y = region, fill = regime)) +
geom_density_ridges(color = "white", size = 2, alpha = 0.9, scale = 2) -> my_density_plot``````

And change the graph theme:

``````my_density_plot + bbplot::bbc_style() +
theme(legend.key.size = unit(2.5, 'cm')) +
scale_fill_manual(values = c("#9a031e","#00a896","#e36414","#0f4c5c")) +
scale_color_manual(values = c("#9a031e","#00a896","#e36414","#0f4c5c")) ``````

Next, we can also check out Pearson’s correlations of some of the variables in our dataset. We can make these plots with the `GGally `package.

The `ggpairs()` argument shows a scatterplot, a density plot and correlation matrix.

``````my_df %>%
filter(year == 2018) %>%
select(regime,
corruption,
civ_soc,
rule_law,
physical,
gdp_growth) %>%
ggpairs(columns = 2:5,
ggplot2::aes(colour = as.factor(regime),
alpha = 0.9)) +
bbplot::bbc_style() +
scale_fill_manual(values = c("#9a031e","#00a896","#e36414","#0f4c5c")) +
scale_color_manual(values = c("#9a031e","#00a896","#e36414","#0f4c5c"))``````

We can use the ggside package to stack graphs together into one plot.

There are a few arguments to add when we choose where we want to place each graph.

For example, `geom_xsideboxplot(aes(y = freedom_house), orientation = "y")` places a boxplot for the three Freedom House democracy levels on the top of the graph, running across the x axis. If we wanted the boxplot along the y axis we would write `geom_ysideboxplot`(). We add `orientation = "y"` to indicate the direction of the boxplots.

Next we indiciate how big we want each graph to be in the panel with `theme(ggside.panel.scale = .5)` argument. This makes the scatterplot take up half and the boxplot the other half. If we write .3, the scatterplot takes up 70% and the boxplot takes up the remainning 30%. Last we indicade `scale_xsidey_discrete()` so the graph doesn’t think it is a continuous variable.

We add Darjeeling Limited color palette from the Wes Anderson movie.

Click here to learn about adding Wes Anderson theme colour palettes to graphs and plots.

``````my_df %>%
filter(year == 2018) %>%
filter(!is.na(fh_number)) %>%
mutate(freedom_house = ifelse(fh_number == 1, "Free",
ifelse(fh_number == 2, "Partly Free", "Not Free"))) %>%
mutate(freedom_house = forcats::fct_relevel(freedom_house, "Not Free", "Partly Free", "Free")) %>%
ggplot(aes(x = freedom_from_torture, y = corruption_level, colour = as.factor(freedom_house))) +
geom_point(size = 4.5, alpha = 0.9) +
geom_smooth(method = "lm", color ="#1d3557", alpha = 0.4) +
geom_xsideboxplot(aes(y = freedom_house), orientation = "y", size = 2) +
theme(ggside.panel.scale = .3) +
scale_xsidey_discrete() +
bbplot::bbc_style() +
facet_wrap(~region) +
scale_color_manual(values= wes_palette("Darjeeling1", n = 3))
``````

The next plot will look how variables change over time.

We can check out if there are changes in the volume and proportion of a variable across time with the `geom_stream(type = "ridge")` from the `ggstream `package.

In this instance, we will compare urban populations across regions from 1800s to today.

``````my_df %>%
group_by(region, year) %>%
summarise(mean_urbanization = mean(urban_population_percentage, na.rm = TRUE)) %>%
ggplot(aes(x = year, y = mean_urbanization, fill = region)) +
geom_stream(type = "ridge") -> my_streamplot``````

And add the theme changes

``````  my_streamplot + ggthemes::theme_pander() +
theme(
legend.title = element_blank(),
legend.position = "bottom",
legend.text = element_text(size = 25),
axis.text.x = element_text(size = 25),
axis.title.y = element_blank(),
axis.title.x = element_blank()) +
scale_fill_manual(values = c("#001219",
"#0a9396",
"#e9d8a6",
"#ee9b00",
"#ca6702",
"#ae2012")) ``````

We can also look at interquartile ranges and spread across variables.

We will look at the urbanization rate across the different regions. The variable is calculated as the ratio of urban population to total country population.

Before, we will create a hex color vector so we are not copying and pasting the colours too many times.

``````my_palette <- c("#1d3557",
"#0a9396",
"#e9d8a6",
"#ee9b00",
"#ca6702",
"#ae2012")``````

We use the `facet_wrap(~year) `so we can separate the three years and compare them.

``````my_df %>%
filter(year == 1980 | year == 1990 | year == 2000)  %>%
ggplot(mapping = aes(x = region,
y = urban_population_percentage,
fill = region)) +
geom_jitter(aes(color = region),
size = 3, alpha = 0.5, width = 0.15) +
geom_boxplot(alpha = 0.5) + facet_wrap(~year) +
scale_fill_manual(values = my_palette) +
scale_color_manual(values = my_palette) +
coord_flip() +
bbplot::bbc_style()``````

If we want to look more closely at one year and print out the country names for the countries that are outliers in the graph, we can run the following function and find the outliers int he dataset for the year 1990:

``````is_outlier <- function(x) {
return(x < quantile(x, 0.25) - 1.5 * IQR(x) | x > quantile(x, 0.75) + 1.5 * IQR(x))
}``````

We can then choose one year and create a binary variable with the function

``````my_df_90 <- my_df %>%
filter(year == 1990) %>%
filter(!is.na(urban_population_percentage))

my_df_90\$my_outliers <- is_outlier(my_df_90\$urban_population_percentage)``````

And we plot the graph:

``````my_df_90 %>%
ggplot(mapping = aes(x = region, y = urban_population_percentage, fill = region)) +
geom_jitter(aes(color = region), size = 3, alpha = 0.5, width = 0.15) +
geom_boxplot(alpha = 0.5) +
geom_text_repel(data = my_df_90[which(my_df_90\$my_outliers == TRUE),],
aes(label = country_name), size = 5) +
scale_fill_manual(values = my_palette) +
scale_color_manual(values = my_palette) +
coord_flip() +
bbplot::bbc_style()
``````

In the next blog post, we will look at t-tests, ANOVAs (and their non-parametric alternatives) to see if the difference in means / medians is statistically significant and meaningful for the underlying population.

# Create a correlation matrix with GGally package in R We can create very informative correlation matrix graphs with one function.

Packages we will need:

``````library(GGally)
library(bbplot) #for pretty themes``````

First, choose some nice hex colors.

``my_palette <- c("#005D8F", "#F2A202")``

Next, we can go create a dichotomous factor variable and divide the continuous “freedom from torture scale” variable into either above the median or below the median score. It’s a crude measurement but it serves to highlight trends.

Blue means the country enjoys high freedom from torture. Yellow means the county suffers from low freedom from torture and people are more likely to be tortured by their government.

Then we feed our variables into the `ggpairs()` function from the `GGally `package.

I use the `columnLabels `to label the graphs with their full names and the `mapping `argument to choose my own color palette.

I add the `bbc_style()` format to the `corr_matrix `object because I like the font and size of this theme. And voila, we have our basic correlation matrix (Figure 1).

``````corr_matrix <- vdem90 %>%
dplyr::mutate(
freedom_torture = ifelse(torture >= 0.65, "High", "Low"),
freedom_torture = as.factor(freedom_t))
dplyr::select(freedom_torture, civil_lib, class_eq) %>%
ggpairs(columnLabels = c('Freedom from Torture', 'Civil Liberties', 'Class Equality'),
mapping = ggplot2::aes(colour = freedom_torture)) +
scale_fill_manual(values = my_palette) +
scale_color_manual(values = my_palette)

corr_matrix + bbplot::bbc_style()``````

First off, in Figure 2 we can see the centre plots in the diagonal are the distribution plots of each variable in the matrix

In Figure 3, we can look at the box plot for the ‘civil liberties index’ score for both high (blue) and low (yellow) ‘freedom from torture’ categories.

The median civil liberties score for countries in the high ‘freedom from torture’ countries is far higher than in countries with low ‘freedom from torture’ (i.e. citizens in these countries are more likely to suffer from state torture). The spread / variance is also far great in states with more torture.