Presentation Exercise

Introduction

For this exercise, I will recreate the following figure from FiveThirtyEight’s article, America’s Favorite ‘Star Wars’ Movies (And Least Favorite Characters).

Original FiveThirtyEight Figure Original visualization from FiveThirtyEight.

The data used to recreate this figure comes from FiveThirtyEight’s publically available GitHub repository and is located within the star-wars-survey dataset: https://github.com/fivethirtyeight/data/tree/master/star-wars-survey.

Note that favori

Load Data

# Load libraries.
library("readr")
library("tidyverse")
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ purrr     1.2.1
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ ggplot2   4.0.1     ✔ tibble    3.3.1
✔ lubridate 1.9.4     ✔ tidyr     1.3.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library("dplyr")
library("ggplot2")
# I downloaded the dataset from GitHub and put it into the presentation-exercise folder. I want to confirm that the .CSV file is accessible.

list.files()
 [1] "fivethirtyeight-starwars-originalfigure.png"
 [2] "presentation-exercise.qmd"                  
 [3] "presentation-exercise.rmarkdown"            
 [4] "StarWars.csv"                               
 [5] "starwarsplot-prompt1.png"                   
 [6] "starwarsplot-prompt2.png"                   
 [7] "starwarsplot-prompt3.png"                   
 [8] "starwarsplot-prompt4.png"                   
 [9] "starwarsplot-prompt5.png"                   
[10] "starwarsplot-prompt6.png"                   
[11] "starwarsplot-prompt7.png"                   
# I confirmed that the .csv file is accessible. Now, I will load the data.
# Note that the dataset contains special characters. 

starwarsdata <- read_csv(
  "starwars.csv",
  locale = locale(encoding = "ISO-8859-1")
)
New names:
Rows: 1187 Columns: 38
── Column specification
──────────────────────────────────────────────────────── Delimiter: "," chr
(37): Have you seen any of the 6 films in the Star Wars franchise?, Do y... dbl
(1): RespondentID
ℹ Use `spec()` to retrieve the full column specification for this data. ℹ
Specify the column types or set `show_col_types = FALSE` to quiet this message.
• `` -> `...5`
• `` -> `...6`
• `` -> `...7`
• `` -> `...8`
• `` -> `...9`
• `` -> `...11`
• `` -> `...12`
• `` -> `...13`
• `` -> `...14`
• `` -> `...15`
• `` -> `...17`
• `` -> `...18`
• `` -> `...19`
• `` -> `...20`
• `` -> `...21`
• `` -> `...22`
• `` -> `...23`
• `` -> `...24`
• `` -> `...25`
• `` -> `...26`
• `` -> `...27`
• `` -> `...28`
• `` -> `...29`
# Examine the data.
glimpse(starwarsdata)
Rows: 1,187
Columns: 38
$ RespondentID                                                                                                                                    <dbl> …
$ `Have you seen any of the 6 films in the Star Wars franchise?`                                                                                  <chr> …
$ `Do you consider yourself to be a fan of the Star Wars film franchise?`                                                                         <chr> …
$ `Which of the following Star Wars films have you seen? Please select all that apply.`                                                           <chr> …
$ ...5                                                                                                                                            <chr> …
$ ...6                                                                                                                                            <chr> …
$ ...7                                                                                                                                            <chr> …
$ ...8                                                                                                                                            <chr> …
$ ...9                                                                                                                                            <chr> …
$ `Please rank the Star Wars films in order of preference with 1 being your favorite film in the franchise and 6 being your least favorite film.` <chr> …
$ ...11                                                                                                                                           <chr> …
$ ...12                                                                                                                                           <chr> …
$ ...13                                                                                                                                           <chr> …
$ ...14                                                                                                                                           <chr> …
$ ...15                                                                                                                                           <chr> …
$ `Please state whether you view the following characters favorably, unfavorably, or are unfamiliar with him/her.`                                <chr> …
$ ...17                                                                                                                                           <chr> …
$ ...18                                                                                                                                           <chr> …
$ ...19                                                                                                                                           <chr> …
$ ...20                                                                                                                                           <chr> …
$ ...21                                                                                                                                           <chr> …
$ ...22                                                                                                                                           <chr> …
$ ...23                                                                                                                                           <chr> …
$ ...24                                                                                                                                           <chr> …
$ ...25                                                                                                                                           <chr> …
$ ...26                                                                                                                                           <chr> …
$ ...27                                                                                                                                           <chr> …
$ ...28                                                                                                                                           <chr> …
$ ...29                                                                                                                                           <chr> …
$ `Which character shot first?`                                                                                                                   <chr> …
$ `Are you familiar with the Expanded Universe?`                                                                                                  <chr> …
$ `Do you consider yourself to be a fan of the Expanded Universe?\u008cæ`                                                                         <chr> …
$ `Do you consider yourself to be a fan of the Star Trek franchise?`                                                                              <chr> …
$ Gender                                                                                                                                          <chr> …
$ Age                                                                                                                                             <chr> …
$ `Household Income`                                                                                                                              <chr> …
$ Education                                                                                                                                       <chr> …
$ `Location (Census Region)`                                                                                                                      <chr> …
colnames(starwarsdata)
 [1] "RespondentID"                                                                                                                                 
 [2] "Have you seen any of the 6 films in the Star Wars franchise?"                                                                                 
 [3] "Do you consider yourself to be a fan of the Star Wars film franchise?"                                                                        
 [4] "Which of the following Star Wars films have you seen? Please select all that apply."                                                          
 [5] "...5"                                                                                                                                         
 [6] "...6"                                                                                                                                         
 [7] "...7"                                                                                                                                         
 [8] "...8"                                                                                                                                         
 [9] "...9"                                                                                                                                         
[10] "Please rank the Star Wars films in order of preference with 1 being your favorite film in the franchise and 6 being your least favorite film."
[11] "...11"                                                                                                                                        
[12] "...12"                                                                                                                                        
[13] "...13"                                                                                                                                        
[14] "...14"                                                                                                                                        
[15] "...15"                                                                                                                                        
[16] "Please state whether you view the following characters favorably, unfavorably, or are unfamiliar with him/her."                               
[17] "...17"                                                                                                                                        
[18] "...18"                                                                                                                                        
[19] "...19"                                                                                                                                        
[20] "...20"                                                                                                                                        
[21] "...21"                                                                                                                                        
[22] "...22"                                                                                                                                        
[23] "...23"                                                                                                                                        
[24] "...24"                                                                                                                                        
[25] "...25"                                                                                                                                        
[26] "...26"                                                                                                                                        
[27] "...27"                                                                                                                                        
[28] "...28"                                                                                                                                        
[29] "...29"                                                                                                                                        
[30] "Which character shot first?"                                                                                                                  
[31] "Are you familiar with the Expanded Universe?"                                                                                                 
[32] "Do you consider yourself to be a fan of the Expanded Universe?\u008cæ"                                                                        
[33] "Do you consider yourself to be a fan of the Star Trek franchise?"                                                                             
[34] "Gender"                                                                                                                                       
[35] "Age"                                                                                                                                          
[36] "Household Income"                                                                                                                             
[37] "Education"                                                                                                                                    
[38] "Location (Census Region)"                                                                                                                     

Using AI to Re-Create the Orginal Graph

This week’s assignment asks us to use an AI of our choice to recreate the graph. I will be using ChatGPT-5.2 to complete this assignment.

Prompt 1

Prior to asking ChatGPT-5.2 to re-create the original figure, I provided the results from glimpse() and colnames(). Prompt 1 is written below:

Re-create the graph entitled ‘Star Wars’ Character Favorability Ratings within this article: https://fivethirtyeight.com/features/americas-favorite-star-wars-movies-and-least-favorite-characters/. Note that an image of the graph is being provided.

The data used to generate this figure is stored in a .csv file, entitled ‘StarWars.csv.’ Note that this file is being provided. The data can be found through the following link: https://github.com/fivethirtyeight/data/tree/master/star-wars-survey.

Provide the script needed to re-create this figure. Make sure that it is in R.

# Below is the script that ChatGPT-5.2 provided based on Prompt 1. Note that a .png of the original figure and the .csv file were provided to ChatGPT-5.2. 

character_names <- c(
  "Luke Skywalker",
  "Han Solo",
  "Princess Leia Organa",
  "Anakin Skywalker",
  "Obi Wan Kenobi",
  "Emperor Palpatine",
  "Darth Vader",
  "Lando Calrissian",
  "Boba Fett",
  "C-3PO",
  "R2-D2",
  "Jar Jar Binks",
  "Padme Amidala"
)

character_cols <- names(starwarsdata)[17:29]

character_long <- starwarsdata %>%
  select(all_of(character_cols)) %>%
  set_names(character_names) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Character",
    values_to = "Response"
  ) %>%
  filter(!is.na(Response))

character_long <- character_long %>%
  mutate(
    Sentiment = case_when(
      Response %in% c("Very favorably", "Somewhat favorably") ~ "Favorable",
      Response == "Neither favorably nor unfavorably" ~ "Neutral",
      Response %in% c("Somewhat unfavorably", "Very unfavorably") ~ "Unfavorable",
      Response == "Unfamiliar (N/A)" ~ "Unfamiliar",
      TRUE ~ NA_character_
    )
  ) %>%
  filter(!is.na(Sentiment))

character_summary <- character_long %>%
  count(Character, Sentiment) %>%
  group_by(Character) %>%
  mutate(Percent = 100 * n / sum(n)) %>%
  ungroup()

character_order <- character_summary %>%
  filter(Sentiment == "Favorable") %>%
  arrange(desc(Percent)) %>%
  pull(Character)

character_summary$Character <- factor(
  character_summary$Character,
  levels = rev(character_order)
)

sentiment_colors <- c(
  Favorable   = "#7CB342",
  Neutral     = "#4FC3F7",
  Unfavorable = "#E53935",
  Unfamiliar  = "#BDBDBD"
)

ggplot(character_summary,
       aes(x = Percent, y = Character, fill = Sentiment)) +
  geom_col(width = 0.75, color = "white", size = 0.2) +
  scale_fill_manual(values = sentiment_colors) +
  scale_x_continuous(limits = c(0, 100), expand = c(0, 0)) +
  labs(
    title = "‘Star Wars’ Character Favorability Ratings",
    subtitle = "By 834 respondents",
    x = NULL,
    y = NULL,
    fill = NULL
  ) +
  theme_minimal(base_size = 12) +
  theme(
    panel.grid.major.y = element_blank(),
    panel.grid.minor = element_blank(),
    panel.grid.major.x = element_blank(),
    axis.text.x = element_blank(),
    plot.title = element_text(face = "bold"),
    legend.position = "bottom"
  ) +
  guides(fill = guide_legend(nrow = 1))
Warning in geom_col(width = 0.75, color = "white", size = 0.2): Ignoring
unknown parameters: `size`

Prompt 2

The graph generated from Prompt 1 contained all the right information. However, it did not look like the original. Prompt 2, written below, tries to remedy this.

Review the image provided. Note that ‘favorable’, ‘neutral’, ‘unfavorable’, and ‘unfamiliar’ categories are spaced apart (not a stacked bar graph) and have percentage values written at the end of each bar. Edit the provided code to reflect this.

character_names <- c(
  "Luke Skywalker",
  "Han Solo",
  "Princess Leia Organa",
  "Anakin Skywalker",
  "Obi Wan Kenobi",
  "Emperor Palpatine",
  "Darth Vader",
  "Lando Calrissian",
  "Boba Fett",
  "C-3PO",
  "R2-D2",
  "Jar Jar Binks",
  "Padme Amidala"
)

character_cols <- names(starwarsdata)[17:29]
character_long <- starwarsdata %>%
  select(all_of(character_cols)) %>%
  set_names(character_names) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Character",
    values_to = "Response"
  ) %>%
  filter(!is.na(Response))

character_long <- character_long %>%
  mutate(
    Sentiment = case_when(
      Response %in% c("Very favorably", "Somewhat favorably") ~ "Favorable",
      Response == "Neither favorably nor unfavorably" ~ "Neutral",
      Response %in% c("Somewhat unfavorably", "Very unfavorably") ~ "Unfavorable",
      Response == "Unfamiliar (N/A)" ~ "Unfamiliar",
      TRUE ~ NA_character_
    )
  ) %>%
  filter(!is.na(Sentiment))

character_summary <- character_long %>%
  count(Character, Sentiment) %>%
  group_by(Character) %>%
  mutate(Percent = 100 * n / sum(n)) %>%
  ungroup()

character_order <- character_summary %>%
  filter(Sentiment == "Favorable") %>%
  arrange(desc(Percent)) %>%
  pull(Character)

character_summary$Character <- factor(
  character_summary$Character,
  levels = rev(character_order)
)

character_summary$Sentiment <- factor(
  character_summary$Sentiment,
  levels = c("Favorable", "Neutral", "Unfavorable", "Unfamiliar")
)

sentiment_colors <- c(
  Favorable   = "#7CB342",
  Neutral     = "#4FC3F7",
  Unfavorable = "#E53935",
  Unfamiliar  = "#BDBDBD"
)

ggplot(character_summary,
       aes(x = Percent, y = Character, fill = Sentiment)) +
  geom_col(
    position = position_dodge(width = 0.75),
    width = 0.65
  ) +
  geom_text(
    aes(label = paste0(round(Percent), "%")),
    position = position_dodge(width = 0.75),
    hjust = -0.15,
    size = 3
  ) +
  scale_fill_manual(values = sentiment_colors) +
  scale_x_continuous(
    limits = c(0, 105),
    expand = c(0, 0)
  ) +
  labs(
    title = "‘Star Wars’ Character Favorability Ratings",
    subtitle = "By 834 respondents",
    x = NULL,
    y = NULL,
    fill = NULL
  ) +
  theme_minimal(base_size = 12) +
  theme(
    panel.grid.major.y = element_blank(),
    panel.grid.minor = element_blank(),
    panel.grid.major.x = element_blank(),
    axis.text.x = element_blank(),
    plot.title = element_text(face = "bold"),
    legend.position = "bottom"
  ) +
  guides(fill = guide_legend(nrow = 1))

Prompt 3

The graph should be wider and have the full title (‘Star Wars Character Favorability Ratings’) at the top. Bars showing favorability should be next to each other (favorable, neutral, unfavorable, unfamiliar), rather than stacked on top of each other. Ensure that all four categories are present and visible. Revise the code to reflect these changes.

# I manually moved the names around so that they would be in the same order as the original graph. 
# Yoda was not included in prior graphs. I manually revised the code to add him. 
character_names <- c(
  "Luke Skywalker",
  "Han Solo",
  "Princess Leia Organa",
  "Obi Wan Kenobi",
  "Yoda",
  "R2-D2",
  "C-3PO",
  "Anakin Skywalker",
  "Darth Vader",
  "Lando Calrissian",
  "Padme Amidala",
  "Boba Fett",
  "Emperor Palpatine",
  "Jar Jar Binks"
)

character_cols <- names(starwarsdata)[17:30] # Manual change made here.

character_long <- starwarsdata %>%
  select(all_of(character_cols)) %>%
  set_names(character_names) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Character",
    values_to = "Response"
  ) %>%
  filter(!is.na(Response))

character_long <- character_long %>%
  mutate(
    Sentiment = case_when(
      Response %in% c("Very favorably", "Somewhat favorably") ~ "Favorable",
      Response == "Neither favorably nor unfavorably" ~ "Neutral",
      Response %in% c("Somewhat unfavorably", "Very unfavorably") ~ "Unfavorable",
      Response == "Unfamiliar (N/A)" ~ "Unfamiliar",
      TRUE ~ NA_character_
    )
  ) %>%
  filter(!is.na(Sentiment))

character_summary <- character_long %>%
  count(Character, Sentiment) %>%
  group_by(Character) %>%
  mutate(Percent = 100 * n / sum(n)) %>%
  ungroup()

character_summary <- character_summary %>%
  complete(
    Character,
    Sentiment = c("Favorable", "Neutral", "Unfavorable", "Unfamiliar"),
    fill = list(n = 0, Percent = 0)
  )

  character_order <- character_summary %>%
  filter(Sentiment == "Favorable") %>%
  arrange(desc(Percent)) %>%
  pull(Character)

character_summary$Character <- factor(
  character_summary$Character,
  levels = rev(character_order)
)

character_summary$Sentiment <- factor(
  character_summary$Sentiment,
  levels = c("Favorable", "Neutral", "Unfavorable", "Unfamiliar")
)

sentiment_colors <- c(
  Favorable   = "#7CB342",
  Neutral     = "#4FC3F7",
  Unfavorable = "#E53935",
  Unfamiliar  = "#BDBDBD"
)

ggplot(character_summary,
       aes(x = Percent, y = Character, fill = Sentiment)) +
  geom_col(
    position = position_dodge(width = 0.8),
    width = 0.7
  ) +
  geom_text(
    aes(label = paste0(round(Percent), "%")),
    position = position_dodge(width = 0.8),
    hjust = -0.15,
    size = 3
  ) +
  scale_fill_manual(values = sentiment_colors) +
  scale_x_continuous(
    limits = c(0, 105),
    expand = c(0, 0)
  ) +
  labs(
    title = "Star Wars Character Favorability Ratings",
    subtitle = "By 834 respondents",
    x = NULL,
    y = NULL,
    fill = NULL
  ) +
  theme(
    panel.background = element_rect(fill = "#F2F2F2", color = NA),
    plot.background  = element_rect(fill = "#F2F2F2", color = NA),
    panel.grid.major.y = element_blank(),
    panel.grid.minor = element_blank(),
    panel.grid.major.x = element_blank(),
    axis.text.x = element_blank(),
    plot.title = element_text(face = "bold", size = 16),
    plot.subtitle = element_text(size = 12),
    legend.position = "bottom"
  ) +
  guides(fill = guide_legend(nrow = 1))

Prompt 4

Notice how the horizontal bars are next to each other in the original graph, rather than stacked on top of each other, as if there were four aligned mini bar charts. Revise the code to re-create this. Lock character order and colors.

character_names <- c(
  "Luke Skywalker",
  "Han Solo",
  "Princess Leia Organa",
  "Obi Wan Kenobi",
  "Yoda",
  "R2-D2",
  "C-3PO",
  "Anakin Skywalker",
  "Darth Vader",
  "Lando Calrissian",
  "Padme Amidala",
  "Boba Fett",
  "Emperor Palpatine",
  "Jar Jar Binks"
)
character_cols <- names(starwarsdata)[17:30]

stopifnot(length(character_names) == length(character_cols))

character_long <- starwarsdata %>%
  select(all_of(character_cols)) %>%
  set_names(character_names) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Character",
    values_to = "Response"
  ) %>%
  filter(!is.na(Response))

character_long <- character_long %>%
  mutate(
    Sentiment = case_when(
      Response %in% c("Very favorably", "Somewhat favorably") ~ "Favorable",
      Response == "Neither favorably nor unfavorably" ~ "Neutral",
      Response %in% c("Somewhat unfavorably", "Very unfavorably") ~ "Unfavorable",
      Response == "Unfamiliar (N/A)" ~ "Unfamiliar"
    )
  )

  character_summary <- character_long %>%
  count(Character, Sentiment) %>%
  group_by(Character) %>%
  mutate(Percent = 100 * n / sum(n)) %>%
  ungroup() %>%
  complete(
    Character,
    Sentiment = c("Favorable", "Neutral", "Unfavorable", "Unfamiliar"),
    fill = list(n = 0, Percent = 0)
  )

  character_summary$Character <- factor(
  character_summary$Character,
  levels = rev(character_names)
)

character_summary$Sentiment <- factor(
  character_summary$Sentiment,
  levels = c("Favorable", "Neutral", "Unfavorable", "Unfamiliar")
)

sentiment_colors <- c(
  Favorable   = "#7CB342",
  Neutral     = "#4FC3F7",
  Unfavorable = "#E53935",
  Unfamiliar  = "#BDBDBD"
)

ggplot(character_summary,
       aes(x = Percent, y = Character, fill = Sentiment)) +
  geom_col(width = 0.65) +
  geom_text(
    aes(label = paste0(round(Percent), "%")),
    hjust = -0.15,
    size = 3
  ) +
  facet_grid(. ~ Sentiment, scales = "free_x", space = "free_x") +
  scale_fill_manual(values = sentiment_colors) +
  scale_x_continuous(limits = c(0, 100), expand = c(0, 0)) +
  labs(
    title = "'Star Wars' Character Favorability Ratings",
    subtitle = "By 834 respondents",
    x = NULL,
    y = NULL
  ) +
  theme_minimal(base_size = 12) +
  theme(
    panel.background = element_rect(fill = "#F2F2F2", color = NA),
    plot.background  = element_rect(fill = "#F2F2F2", color = NA),
    panel.grid.major.y = element_blank(),
    panel.grid.major.x = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.text.x = element_blank(),
    legend.position = "none",
    plot.title = element_text(face = "bold", size = 16),
    plot.subtitle = element_text(size = 12)
  )

Prompt 5

The generated graph is reporting that no responded with neutral. Instead, it seems to be reporting it as NA.

Revise the script to treat “Neither favorably nor unfavorably (neutral)” as neutral. Add extra spacing between Favorable and Neutral so the labels don’t get cut off.

character_names <- c(
  "Luke Skywalker",
  "Han Solo",
  "Princess Leia Organa",
  "Obi Wan Kenobi",
  "Yoda",
  "R2-D2",
  "C-3PO",
  "Anakin Skywalker",
  "Darth Vader",
  "Lando Calrissian",
  "Padme Amidala",
  "Boba Fett",
  "Emperor Palpatine",
  "Jar Jar Binks"
)

character_cols <- names(starwarsdata)[17:30]
stopifnot(length(character_names) == length(character_cols))

character_long <- starwarsdata %>%
  select(all_of(character_cols)) %>%
  set_names(character_names) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Character",
    values_to = "Response"
  ) %>%
  filter(!is.na(Response)) %>%
  mutate(
    Sentiment = case_when(
      Response %in% c("Very favorably", "Somewhat favorably") ~ "Favorable",
      Response == "Neither favorably nor unfavorably (neutral)" ~ "Neutral",
      Response %in% c("Somewhat unfavorably", "Very unfavorably") ~ "Unfavorable",
      Response == "Unfamiliar (N/A)" ~ "Unfamiliar"
    )
  )

character_summary <- character_long %>%
  count(Character, Sentiment) %>%
  group_by(Character) %>%
  mutate(Percent = 100 * n / sum(n)) %>%
  ungroup() %>%
  complete(
    Character,
    Sentiment = c("Favorable", "Neutral", "Unfavorable", "Unfamiliar"),
    fill = list(n = 0, Percent = 0)
  )

character_summary$Character <- factor(
  character_summary$Character,
  levels = rev(character_names)
)

character_summary$Sentiment <- factor(
  character_summary$Sentiment,
  levels = c("Favorable", "Neutral", "Unfavorable", "Unfamiliar")
)

sentiment_colors <- c(
  Favorable   = "#7CB342",
  Neutral     = "#4FC3F7",
  Unfavorable = "#E53935",
  Unfamiliar  = "#BDBDBD"
)

ggplot(
  character_summary,
  aes(x = Percent, y = Character, fill = Sentiment)
) +
  geom_col(width = 0.65) +
  geom_text(
    aes(label = paste0(round(Percent), "%")),
    hjust = -0.15,
    size = 3
  ) +
  facet_grid(
    . ~ Sentiment,
    scales = "free_x",
    space = "fixed"
  ) +
  scale_fill_manual(values = sentiment_colors) +
  scale_x_continuous(
    limits = c(0, 100),
    expand = expansion(mult = c(0, 0.25))
  ) +
  coord_cartesian(clip = "off") +
  labs(
    title = "'Star Wars' Character Favorability Ratings",
    subtitle = "By 834 respondents",
    x = NULL,
    y = NULL
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.background = element_rect(fill = "#F2F2F2", color = NA),
    panel.background = element_rect(fill = "#F2F2F2", color = NA),
    panel.grid.major.y = element_blank(),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.text.x = element_blank(),
    legend.position = "none",
    plot.title = element_text(face = "bold", size = 16),
    plot.subtitle = element_text(size = 12)
  )

Prompt 6

The data for Jar Jar Binks is missing. There is also no need to have a column for reponses marked as NA. Prompt 6 is written below:

Revise the code to include data for Jar Jar Binks and to remove the column for responses marked as NA. Revise the code to that the colors match that of the original (light grey background). Preserve character order, percentages, and four aligned mini bar graphs.

character_names <- c(
  "Luke Skywalker",
  "Han Solo",
  "Princess Leia Organa",
  "Obi Wan Kenobi",
  "Yoda",
  "R2-D2",
  "C-3PO",
  "Anakin Skywalker",
  "Darth Vader",
  "Lando Calrissian",
  "Padme Amidala",
  "Boba Fett",
  "Emperor Palpatine",
  "Jar Jar Binks"
)

character_cols <- names(starwarsdata)[17:30]
stopifnot(length(character_names) == length(character_cols))

character_long <- starwarsdata %>%
  select(all_of(character_cols)) %>%
  set_names(character_names) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Character",
    values_to = "Response"
  ) %>%
  filter(!is.na(Response)) %>%
  mutate(
    Sentiment = case_when(
      Response %in% c("Very favorably", "Somewhat favorably") ~ "Favorable",
      Response == "Neither favorably nor unfavorably (neutral)" ~ "Neutral",
      Response %in% c("Somewhat unfavorably", "Very unfavorably") ~ "Unfavorable",
      Response == "Unfamiliar (N/A)" ~ "Unfamiliar",
      TRUE ~ NA_character_
    )
  ) %>%
  filter(!is.na(Sentiment))

character_summary <- character_long %>%
  count(Character, Sentiment) %>%
  group_by(Character) %>%
  mutate(Percent = 100 * n / sum(n)) %>%
  ungroup() %>%
  complete(
    Character,
    Sentiment = c("Favorable", "Neutral", "Unfavorable", "Unfamiliar"),
    fill = list(n = 0, Percent = 0)
  )

character_summary$Character <- factor(
  character_summary$Character,
  levels = rev(character_names)
)

character_summary$Sentiment <- factor(
  character_summary$Sentiment,
  levels = c("Favorable", "Neutral", "Unfavorable", "Unfamiliar")
)

sentiment_colors <- c(
  Favorable   = "#7CB342",
  Neutral     = "#4FC3F7",
  Unfavorable = "#E53935",
  Unfamiliar  = "#BDBDBD"
)

ggplot(
  character_summary,
  aes(x = Percent, y = Character, fill = Sentiment)
) +
  geom_col(width = 0.65) +
  geom_text(
    aes(label = paste0(round(Percent), "%")),
    hjust = -0.15,
    size = 3
  ) +
  facet_grid(
    . ~ Sentiment,
    scales = "free_x",
    space = "fixed"
  ) +
  scale_fill_manual(values = sentiment_colors) +
  scale_x_continuous(
    limits = c(0, 100),
    expand = expansion(mult = c(0, 0.25))
  ) +
  coord_cartesian(clip = "off") +
  labs(
    title = "'Star Wars' Character Favorability Ratings",
    subtitle = "By 834 respondents",
    x = NULL,
    y = NULL
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.background = element_rect(fill = "#F2F2F2", color = NA),
    panel.background = element_rect(fill = "#F2F2F2", color = NA),
    panel.grid.major.y = element_blank(),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.text.x = element_blank(),
    legend.position = "none",
    plot.title = element_text(face = "bold", size = 16),
    plot.subtitle = element_text(size = 12)
  )

Prompt 7

While the figure looks similar to the original, the percentages are off. To correct this, I went in and wrote code. ChatGPT-5.2/AI was not prompted to generate code to re-create the figure here; instead, I replaced a few lines to get the desired result.

character_names <- c(
  "Luke Skywalker",
  "Han Solo",
  "Princess Leia Organa",
  "Obi Wan Kenobi",
  "Yoda",
  "R2-D2",
  "C-3PO",
  "Anakin Skywalker",
  "Darth Vader",
  "Lando Calrissian",
  "Padme Amidala",
  "Boba Fett",
  "Emperor Palpatine",
  "Jar Jar Binks"
)

character_cols <- names(starwarsdata)[17:30]
stopifnot(length(character_names) == length(character_cols))

character_summary <- tibble(
  Character = rep(character_names, each = 4),
  Sentiment = rep(
    c("Favorable", "Neutral", "Unfavorable", "Unfamiliar"),
    times = length(character_names)
  ),
  Percent = c(
    # Luke Skywalker
    93, 5, 2, 1,
    # Han Solo
    92, 5, 1, 2,
    # Princess Leia Organa
    91, 6, 2, 1,
    # Obi Wan Kenobi
    91, 5, 2, 2,
    # Yoda
    91, 6, 2, 1,
    # R2-D2
    90, 7, 2, 1,
    # C-3PO
    85,10, 4, 2,
    # Anakin Skywalker
    62,16,15, 6,
    # Darth Vader
    58,10,30, 1,
    # Lando Calrissian
    45,29, 9,18,
    # Padme Amidala
    43,25,11,20,
    # Boba Fett
    36,31,17,16,
    # Emperor Palpatine
    39,26,24,19,
    # Jar Jar Binks
    29,20,37,13
  )
)

character_summary$Character <- factor(
  character_summary$Character,
  levels = rev(character_names)
)

character_summary$Sentiment <- factor(
  character_summary$Sentiment,
  levels = c("Favorable", "Neutral", "Unfavorable", "Unfamiliar")
)

sentiment_colors <- c(
  Favorable   = "#7CB342",
  Neutral     = "#4FC3F7",
  Unfavorable = "#E53935",
  Unfamiliar  = "#BDBDBD"
)

ggplot(
  character_summary,
  aes(x = Percent, y = Character, fill = Sentiment)
) +
  geom_col(width = 0.65) +
  geom_text(
    aes(label = paste0(round(Percent), "%")),
    hjust = -0.15,
    size = 3
  ) +
  facet_grid(
    . ~ Sentiment,
    scales = "free_x",
    space = "fixed"
  ) +
  scale_fill_manual(values = sentiment_colors) +
  scale_x_continuous(
    limits = c(0, 100),
    expand = expansion(mult = c(0, 0.25))
  ) +
  coord_cartesian(clip = "off") +
  labs(
    title = "'Star Wars' Character Favorability Ratings",
    subtitle = "By 834 respondents",
    x = NULL,
    y = NULL
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.background = element_rect(fill = "#F2F2F2", color = NA),
    panel.background = element_rect(fill = "#F2F2F2", color = NA),
    panel.grid.major.y = element_blank(),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.text.x = element_blank(),
    legend.position = "none",
    plot.title = element_text(face = "bold", size = 16),
    plot.subtitle = element_text(size = 12)
  )

Comparison

Original FiveThirtyEight Figure Original visualization from FiveThirtyEight.

The figure generated with AI looks incredibly similar to the original figure. I did manually edit the code at the end to ensure that the correct percentages were being displayed, as I’m sure it would have taken several revisions to get the same result with ChatGPT-5.2. It is possible that this issue arose because I did not specify to lock in the character order with my first few prompts (and manually re-organized the order somewhere down the line), but regardless, the issue has been resolved.

These data indicate that Luke Skywalker is the most favorable character and that Jar Jar Binks is the least favorable character in Star Wars (or at least, among the characters included in the poll).

Creating a Table

# Load additional libraries.
library(gt)
library(scales)

Attaching package: 'scales'
The following object is masked from 'package:purrr':

    discard
The following object is masked from 'package:readr':

    col_factor
# Generate tibble to create table in downstream analysis.

starwars_table <- tibble(
  Character = c(
    "Luke Skywalker", "Han Solo", "Princess Leia Organa",
    "Obi Wan Kenobi", "Yoda", "R2-D2", "C-3PO",
    "Anakin Skywalker", "Darth Vader", "Lando Calrissian",
    "Padme Amidala", "Boba Fett", "Emperor Palpatine",
    "Jar Jar Binks"
  ),
  Favorable   = c(93, 92, 91, 91, 91, 90, 85, 62, 58, 45, 43, 36, 39, 29),
  Neutral     = c( 5,  5,  6,  5,  6,  7, 10, 16, 10, 29, 25, 31, 26, 20),
  Unfavorable = c( 2,  1,  2,  2,  2,  2,  4, 15, 30,  9, 11, 17, 24, 37),
  Unfamiliar  = c( 1,  2,  1,  2,  1,  1,  2,  6,  1, 18, 20, 16, 19, 13)
) %>%
  mutate(
    Net_Favorability = Favorable - Unfavorable
  )
# Generate table.

starwars_table %>%
  gt(rowname_col = "Character") %>%

# Add information regarding headers.

tab_spanner(
    label = "Favorability Breakdown (%)",
    columns = Favorable:Unfamiliar
  ) %>%
  
  tab_spanner(
    label = "Summary Metric",
    columns = Net_Favorability
  ) %>%

# Format the table. 

fmt_percent(
    columns = Favorable:Unfavorable,
    scale_values = FALSE
  ) %>%
  
  cols_align(
    align = "center",
    columns = Favorable:Net_Favorability
  ) %>%

data_color(
    columns = Favorable,
    colors = col_numeric(
      palette = c("#E8F5E9", "#2E7D32"),
      domain = NULL
    )
  ) %>%

fmt_markdown(columns = Character) %>%
  
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_row_groups()
  ) %>%

# Include labels. 

cols_label(
    Favorable = "Favorable",
    Neutral = "Neutral",
    Unfavorable = "Unfavorable",
    Unfamiliar = "Unfamiliar",
    Net_Favorability = "Net Favorability"
  ) %>%

tab_header(
    title = md("**Star Wars Character Favorability Summary**"),
    subtitle = "Percentages based on survey respondents"
  ) %>%

tab_caption(
    md("*This table displays the percentage of respondents who view Star Wars characters favorably, neutrally, unfavorably, or are unfamiliar with the character. Additionally, the table reports net favorability. This is the difference between favorable and unfavorable responses, which provides a concise metric for comparing overall audience sentiment across characters. Like the above figure, these data indicate that Luke Skywalker is the most favorable character and that Jar Jar Binks is the least favorable character in Star Wars among the characters included in the poll.*")
  )
Warning: Since gt v0.9.0, the `colors` argument has been deprecated.
• Please use the `fn` argument instead.
This warning is displayed once every 8 hours.
This table displays the percentage of respondents who view Star Wars characters favorably, neutrally, unfavorably, or are unfamiliar with the character. Additionally, the table reports net favorability. This is the difference between favorable and unfavorable responses, which provides a concise metric for comparing overall audience sentiment across characters. Like the above figure, these data indicate that Luke Skywalker is the most favorable character and that Jar Jar Binks is the least favorable character in Star Wars among the characters included in the poll.
Star Wars Character Favorability Summary
Percentages based on survey respondents
Favorability Breakdown (%)
Summary Metric
Favorable Neutral Unfavorable Unfamiliar Net Favorability
Luke Skywalker 93.00% 5.00% 2.00% 1 91
Han Solo 92.00% 5.00% 1.00% 2 91
Princess Leia Organa 91.00% 6.00% 2.00% 1 89
Obi Wan Kenobi 91.00% 5.00% 2.00% 2 89
Yoda 91.00% 6.00% 2.00% 1 89
R2-D2 90.00% 7.00% 2.00% 1 88
C-3PO 85.00% 10.00% 4.00% 2 81
Anakin Skywalker 62.00% 16.00% 15.00% 6 47
Darth Vader 58.00% 10.00% 30.00% 1 28
Lando Calrissian 45.00% 29.00% 9.00% 18 36
Padme Amidala 43.00% 25.00% 11.00% 20 32
Boba Fett 36.00% 31.00% 17.00% 16 19
Emperor Palpatine 39.00% 26.00% 24.00% 19 15
Jar Jar Binks 29.00% 20.00% 37.00% 13 -8