likert_vars <- c(
"Lack_Trust", "Enhance_Pleasure", "Decrease_Pleasure", "Beautiful_Girls", "No_love", "Suggest_Use",
"Morally_wrong", "Messy", "Unprotected_sex", "Heightened_excitement",
"Responsible_sexual_behaviour", "Women_perception", "Embarrassed_Purchasing",
"Confident_putting_on", "Regret_Later"
)
var_labels <- c(
"Lack_Trust" = "Using condoms means lack of trust",
"Enhance_Pleasure" = "Condoms enhance sexual pleasure",
"Decrease_Pleasure" = "Condoms decrease sexual pleasure",
"Beautiful_Girls" = "Beautiful girls are safe",
"No_love" = "Using condoms means lack of love",
"Suggest_Use" = "I feel comfortable suggesting use of condoms",
"Morally_wrong" = "Morally wrong to use condoms",
"Messy" = "Condoms are messy",
"Unprotected_sex" = "Excitement of unprotected sex",
"Heightened_excitement" = "Condom use heightens pleasure",
"Responsible_sexual_behaviour" = "Using a condom is a woman’s responsibility",
"Women_perception" = "Women think men who use condoms cheat",
"Embarrassed_Purchasing" = "Embarrassed purchasing a condom",
"Confident_putting_on" = "Confident in my ability to use a condom",
"Regret_Later" = "I only need to worry later"
)
# Drop rows with NA
df_likert <- df %>%
select(all_of(likert_vars)) %>%
drop_na()
# Reshape data
likert_long <- df_likert %>%
pivot_longer(cols = everything(), names_to = "Variable", values_to = "Response") %>%
mutate(
Variable = recode(Variable, !!!var_labels),
Response = as.numeric(as.character(Response))
) %>%
mutate(
Direction = case_when(
Response %in% c(1,2) ~ "Disagree",
Response == 3 ~ "Neutral",
Response %in% c(4,5) ~ "Agree"
),
ResponseLabel = case_when(
Response == 1 ~ "Strongly Disagree",
Response == 2 ~ "Disagree",
Response == 3 ~ "Neutral",
Response == 4 ~ "Agree",
Response == 5 ~ "Strongly Agree"
)
)
# Percentages
likert_perc <- likert_long %>%
group_by(Variable, ResponseLabel, Direction) %>%
summarise(n = n(), .groups = "drop") %>%
group_by(Variable) %>%
mutate(percent = n / sum(n) * 100) %>%
ungroup()
# Diverging percentages
likert_perc <- likert_perc %>%
mutate(percent_diverge = case_when(
Direction == "Disagree" ~ -percent,
Direction == "Agree" ~ percent,
TRUE ~ 0
))
# Drop unused factor levels for plotting
likert_perc$ResponseLabel <- droplevels(factor(likert_perc$ResponseLabel))
likert_perc$Variable <- fct_rev(factor(likert_perc$Variable))
# Factor order for fill
likert_perc$ResponseLabel <- factor(
likert_perc$ResponseLabel,
levels = c("Strongly Disagree","Disagree","Agree","Strongly Agree")
)
# Max agree for neutral bar offset
max_agree <- max(likert_perc$percent_diverge[likert_perc$Direction=="Agree"])
neutral_offset <- max_agree + 26
# Dynamic x-axis limits
x_min <- floor(min(likert_perc$percent_diverge[likert_perc$Direction != "Neutral"]) / 10) * 10
neutral_max <- max(likert_perc$percent[likert_perc$Direction == "Neutral"])
x_max <- ceiling((neutral_offset + neutral_max) / 10) * 10
# Subset for diverging bars
likert_perc_div <- subset(likert_perc, Direction != "Neutral")
likert_perc_div$ResponseLabel <- factor(
likert_perc_div$ResponseLabel,
levels = c("Strongly Disagree","Disagree","Agree","Strongly Agree")
)
likert_perc_div$Variable <- droplevels(likert_perc_div$Variable)
# Subset for neutral bars with percent > 0
neutral_data <- subset(likert_perc, Direction == "Neutral" & percent > 0)
neutral_data$Variable <- droplevels(neutral_data$Variable)
# Plot
ggplot() +
# Diverging bars
geom_col(
data = likert_perc_div,
aes(x = percent_diverge, y = Variable, fill = ResponseLabel),
width = 0.7
) +
# Neutral bars as thin grey rectangles
geom_rect(
data = neutral_data,
aes(
xmin = neutral_offset,
xmax = neutral_offset + percent,
ymin = as.numeric(Variable) - 0.3,
ymax = as.numeric(Variable) + 0.3
),
fill = "#f0f0f0"
) +
# Neutral labels
geom_text(
data = neutral_data,
aes(
x = neutral_offset + percent + 1,
y = as.numeric(Variable),
label = paste0(round(percent,1),"%")
),
hjust = 0,
size = 3
) +
# Colors for diverging bars
scale_fill_manual(
values = c(
"Strongly Disagree" = "#d73027",
"Disagree" = "#fc8d59",
"Agree" = "#91cf60",
"Strongly Agree" = "#1a9850"
)
) +
# X-axis
scale_x_continuous(
labels = abs,
breaks = seq(x_min, x_max, 10),
limits = c(x_min, x_max)
) +
labs(
x = "Percentage",
y = "",
fill = "Response",
title = "Personal Barriers to Condom Utilization",
subtitle = "Neutrals displayed as separate grey bars"
) +
theme_minimal(base_size = 13) +
theme(
axis.text.y = element_text(face = "bold"),
legend.position = "bottom",
panel.grid.major.x = element_line(color = "gray80", size = 0.3),
panel.grid.minor.x = element_line(color = "gray90", size = 0.2),
plot.subtitle = element_text(size = 11, color = "gray50")
)