data <- read.csv('politics_approval_rates.csv')
df <- data.frame(data)
df
Our goal is to visualize the data with a stacked bar chart. But if you try to make a bar plot, one problem arises: Which value are you going to use as the height? Is it the Approve?
barplot(names.arg=df$Issue, height=df$Approve, col = '#ffddcc')
But that’s not what we want. We want to use all the values to compare them in the same bar.
knitr::include_graphics("stacked_bar.png")
3 elements are important: * Category: the categories are displayed on the x axis (ex: profession) * Subcategory: Each main category contains subcategories stacked on top of each other (ex: gender) * Height: the height of the bar represents the values are displayed on y axis (ex: salary).
Now, we need to find our category, subcategory and opinion:
That’s done. The next step is to trasnform the data.
The final data will looks like this:
knitr::include_graphics("final_df.png")
Each Category will have: * 3 subcategories * 3 heights respective to the subcategories
We have 13 issues, we want to replicated them 3 times because we have 3 subcategories.
# loop through each of the 13 issues
issues <- c()
for (issue in df$Issue)
# replicate the issue 3 times
issues <- c(issues, rep(issue, 3))
# 13 * 3 = 39 issues
issues
[1] "Race relations" "Race relations" "Race relations"
[4] "Education" "Education" "Education"
[7] "Terrorism" "Terrorism" "Terrorism"
[10] "Energy policy" "Energy policy" "Energy policy"
[13] "Foreign affairs" "Foreign affairs" "Foreign affairs"
[16] "Environment" "Environment" "Environment"
[19] "Situation in Iraq" "Situation in Iraq" "Situation in Iraq"
[22] "Taxes" "Taxes" "Taxes"
[25] "Healthcare policy" "Healthcare policy" "Healthcare policy"
[28] "Economy" "Economy" "Economy"
[31] "Situation in Afghanistan" "Situation in Afghanistan" "Situation in Afghanistan"
[34] "Federal budget deficit" "Federal budget deficit" "Federal budget deficit"
[37] "Immigration" "Immigration" "Immigration"
We have 3 opinions: approve, disapprove and no opinion.
opinions <- colnames(df[, 2:4])
opinions
[1] "Approve" "Disapprove" "No.Opinion"
Now we replicate the subcategories. Look at opinions from the final data frame from the picture above. This time we don’t need to loop through each opinion. Instead, we replicate all at once. We have 3 opinions, we replicate them 13 times to get the 39. (3x13 = 39)
# n_replications <- length(issues) / 3 # 39/3 = 13 replications
n_replications <- nrow(df)
opinions <- rep(opinions, n_replications)
opinions
[1] "Approve" "Disapprove" "No.Opinion" "Approve" "Disapprove" "No.Opinion"
[7] "Approve" "Disapprove" "No.Opinion" "Approve" "Disapprove" "No.Opinion"
[13] "Approve" "Disapprove" "No.Opinion" "Approve" "Disapprove" "No.Opinion"
[19] "Approve" "Disapprove" "No.Opinion" "Approve" "Disapprove" "No.Opinion"
[25] "Approve" "Disapprove" "No.Opinion" "Approve" "Disapprove" "No.Opinion"
[31] "Approve" "Disapprove" "No.Opinion" "Approve" "Disapprove" "No.Opinion"
[37] "Approve" "Disapprove" "No.Opinion"
Now we just get the values from each row, then transform it into a 1D vector.
# get the columns that contains the opinion values
values <- df[2:4]
values
Transpose the values
values <- t(values)
values
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
Approve 52 49 48 47 44 43 41 41 40 38 36 31 29
Disapprove 38 40 45 42 48 51 53 54 57 59 57 64 62
No.Opinion 10 11 7 11 8 6 6 5 3 3 7 5 9
Convert them to a vector
values <- as.vector(values)
values
[1] 52 38 10 49 40 11 48 45 7 47 42 11 44 48 8 43 51 6 41 53 6 41 54 5 40 57 3 38 59
[30] 3 36 57 7 31 64 5 29 62 9
Now, we have the rows transposed and stacked of to of each other. Let’s make the combine all the columns (issues, opinions, values) into a data frame.
final_df = data.frame(issues, opinions, values)
colnames(final_df)[3] <- "Approval Rates"
head(final_df)
NA
Beautiful! Now here comes the fun part, visualization!
# load the ggplot2 library
library(ggplot2)
ggplot(final_df, aes(fill=opinions, y=`Approval Rates`, x=issues)) +
geom_bar(position="stack", stat="identity") +
theme(axis.text.x = element_text(angle = 45, margin = margin(t=30, "pt")))
Warning: NAs introduced by coercion
# load the ggplot2 library
library(ggplot2)
ggplot(final_df, aes(x=issues, y=`Approval Rates`, fill=opinions)) +
geom_col(position="dodge") +
theme(axis.text.x = element_text(angle = 45, margin = margin(t=30, "pt")))
Warning: NAs introduced by coercion