Author Likeability

Key_Influencers

Moral Outlook Graphs

ggplot(ASL_SS, aes(x = reorder(`Moral_Outlook`, -table(`Moral_Outlook`)[`Moral_Outlook`]))) +
  geom_bar(fill = "steelblue") +
  coord_flip() +  # horizontal bars for readability
  labs(title = "Distribution of Moral Outlooks",
       x = "Moral Outlook",
       y = "Count") +
  theme_minimal()

ggplot(ASL_Novelette, aes(x = reorder(`Moral_Outlook`, -table(`Moral_Outlook`)[`Moral_Outlook`]))) +
  geom_bar(fill = "steelblue") +
  coord_flip() +  # horizontal bars for readability
  labs(title = "Distribution of Moral Outlooks",
       x = "Moral Outlook",
       y = "Count") +
  theme_minimal()

ggplot(ASL_Novellas, aes(x = reorder(`Moral_Outlook`, -table(`Moral_Outlook`)[`Moral_Outlook`]))) +
  geom_bar(fill = "steelblue") +
  coord_flip() +  # horizontal bars for readability
  labs(title = "Distribution of Moral Outlooks",
       x = "Moral Outlook",
       y = "Count") +
  theme_minimal()

ggplot(ASL_Novels, aes(x = reorder(`Moral_Outlook`, -table(`Moral_Outlook`)[`Moral_Outlook`]))) +
  geom_bar(fill = "steelblue") +
  coord_flip() +  # horizontal bars for readability
  labs(title = "Distribution of Moral Outlooks",
       x = "Moral Outlook",
       y = "Count") +
  theme_minimal()

ggplot(ASL_PF, aes(x = reorder(`Moral_Outlook`, -table(`Moral_Outlook`)[`Moral_Outlook`]))) +
  geom_bar(fill = "steelblue") +
  coord_flip() +  # horizontal bars for readability
  labs(title = "Distribution of Moral Outlooks",
       x = "Moral Outlook",
       y = "Count") +
  theme_minimal()

ggplot(ASL_Poetry_unique, aes(x = reorder(`Moral_Outlook`, -table(`Moral_Outlook`)[`Moral_Outlook`]))) +
  geom_bar(fill = "darkgreen") +
  coord_flip() +  # horizontal bars for readability
  labs(title = "Distribution of Moral Outlooks",
       x = "Moral Outlook",
       y = "Count") +
  theme_minimal()

Pie Chart of nationality with stars

# Step 1: Get top 5 nationalities
top5_nationalities <- ASL_unique %>%
  filter(!is.na(Nationality)) %>%
  count(Nationality, sort = TRUE) %>%
  top_n(5, n) %>%
  pull(Nationality)

# Step 2: Summarize data
nationality_summary <- ASL_unique %>%
  filter(Nationality %in% top5_nationalities) %>%
  group_by(Nationality) %>%
  summarise(
    Count = n(),
    Avg_Stars = round(mean(Stars, na.rm = TRUE), 2)
  ) %>%
  mutate(
    Label = paste0(Nationality, " (", Count, ", ", Avg_Stars, "★)")
  )

# Step 3: Pie chart with legend-only labels
ggplot(nationality_summary, aes(x = "", y = Count, fill = Label)) +
  geom_col(width = 1, color = "white") +
  coord_polar("y") +
  theme_void() +
  labs(title = "Top 5 Nationalities (Count & Avg Stars)") +
  guides(fill = guide_legend(title = "Nationality (Count, Avg Stars)")) +
  theme(
    legend.title = element_text(size = 11, face = "bold"),
    legend.text = element_text(size = 10)
  )

Religion Visualizations

# Summarize top 10 religions by Read Time
religion_read_time <- ASL_unique %>%
  group_by(Religion) %>%
  summarise(Total_Read_Time = sum(Read_Time, na.rm = TRUE)) %>%
  arrange(desc(Total_Read_Time)) %>%
  slice_head(n = 10)

# Create label for legend
religion_read_time <- religion_read_time %>%
  mutate(Religion_Label = paste0(Religion, " (", round(Total_Read_Time, 1), ")"))

# Plot without geom_text
ggplot(religion_read_time, aes(x = reorder(Religion, Total_Read_Time), 
                               y = Total_Read_Time,
                               fill = Religion_Label)) +
  geom_col() +
  coord_flip() +
  scale_fill_manual(
    values = setNames(brewer.pal(n = 10, "Set3"), religion_read_time$Religion_Label),
    name = "Religion (Total Read Time)"
  ) +
  labs(
    title = "Total Read Time by Religion",
    x = "Religion",
    y = "Total Read Time (hours)"
  ) +
  theme_minimal() +
  guides(fill = guide_legend(reverse = TRUE)) +
  theme(
    legend.position = "right",
    legend.title = element_text(size = 10),
    legend.text = element_text(size = 9)
  )

Graph of Genres

ASL_unique %>%
  count(Genre, sort = TRUE) %>%
  ggplot(aes(x = reorder(Genre, n), y = n)) +
  geom_col(fill = "steelblue") +
  coord_flip() +
  labs(
    title = "Genre Distribution",
    x = "Genre",
    y = "Count"
  ) +
  theme_minimal()

ASL_unique %>%
  group_by(Genre) %>%
  summarise(Total_Pages = sum(Pages, na.rm = TRUE)) %>%
  arrange(desc(Total_Pages)) %>%
  ggplot(aes(x = reorder(Genre, Total_Pages), y = Total_Pages)) +
  geom_col(fill = "darkgreen") +
  coord_flip() +
  labs(
    title = "Total Pages by Genre",
    x = "Genre",
    y = "Pages"
  ) +
  theme_minimal()

## In future I will not use count as much.

# Get top 10 genres by count
top_genres <- ASL_unique %>%
  count(Genre, sort = TRUE) %>%
  slice_head(n = 10) %>%
  pull(Genre)

# Filter dataset to those genres
ASL_top_genres <- ASL_unique %>%
  filter(Genre %in% top_genres)

# Calculate total pages read per author per genre
author_pages <- ASL_top_genres %>%
  group_by(Genre, Author) %>%
  summarise(TotalPages = sum(Pages, na.rm = TRUE), .groups = "drop") %>%
  group_by(Genre) %>%
  slice_max(order_by = TotalPages, n = 2) %>%  # Top 5 authors per genre by pages read
  ungroup()

# Reorder Author factor by TotalPages within each Genre for proper legend order
author_pages <- author_pages %>%
  group_by(Genre) %>%
  mutate(Author = fct_reorder(Author, TotalPages)) %>%
  ungroup()

# Plot bar chart
ggplot(author_pages, aes(x = reorder(Genre, -TotalPages), y = TotalPages, fill = Author)) +
  geom_col(position = position_dodge()) +
  labs(
    title = "Top 5 Authors per Top 10 Genres by Pages Read",
    x = "Genre",
    y = "Total Pages Read",
    fill = "Author"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "right"
  )

% of Fictional

fictional_percent <- ASL_unique %>%
  summarise(Percentage_Fictional = round(100 * mean(Fictional == 1, na.rm = TRUE), 1))

print(fictional_percent)
## # A tibble: 1 × 1
##   Percentage_Fictional
##                  <dbl>
## 1                 83.1
ASL_unique <- ASL_unique %>%
  mutate(
    Length_Category = case_when(
      Novel == 1 ~ "Novel",
      Novella == 1 ~ "Novella",
      Novelette == 1 ~ "Novelette",
      Short_Story == 1 ~ "Short Story",
      Poetry == 1 ~ "Poetry",
      TRUE ~ "Other"
    )
  )

fiction_by_length <- ASL_unique %>%
  group_by(Length_Category, Fictional) %>%
  summarise(Count = n(), .groups = "drop") %>%
  group_by(Length_Category) %>%
  mutate(
    Total = sum(Count),
    Percent = round(100 * Count / Total, 1)
  )

ggplot(fiction_by_length, aes(x = reorder(Length_Category, -Total), y = Percent, fill = as.factor(Fictional))) +
  geom_col(position = "dodge") +
  scale_fill_manual(values = c("0" = "gray60", "1" = "darkorange"), labels = c("Nonfiction", "Fiction")) +
  labs(
    title = "Fiction vs. Nonfiction by Length Category",
    x = "Length Category",
    y = "Percentage",
    fill = "Category"
  ) +
  theme_minimal()

## A flat percentage in insufficient, because it fails to consider size of book.

Philosophical View

# First, create a unified 'Length' category
ASL_long <- ASL_unique %>%
  mutate(Length = case_when(
    Short_Story == 1 ~ "Short Story",
    Novelette == 1 ~ "Novelette",
    Novella == 1 ~ "Novella",
    Novel == 1 ~ "Novel",
    Poetry == 1 ~ "Poetry",
    TRUE ~ "Other"
  ))

# Then, group and count by Length and Philosophical View
length_philosophy <- ASL_long %>%
  group_by(Length, Philosophical_View) %>%
  summarise(Count = n(), .groups = "drop")

novel_data <- ASL_long %>%
  filter(Length == "Novel") %>%
  group_by(Philosophical_View) %>%
  summarise(Count = n(), .groups = "drop")

ggplot(novel_data, aes(x = reorder(Philosophical_View, -Count), y = Count, fill = Philosophical_View)) +
  geom_bar(stat = "identity") +
  theme_minimal() +
  labs(
    title = "Philosophical Views in Novels",
    x = "Philosophical View",
    y = "Count"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

## Count is infufficient again.

novel_time <- ASL_long %>%
  filter(Length == "Novel") %>%
  group_by(Philosophical_View) %>%
  summarise(Time_Read = sum(Read_Time, na.rm = TRUE), .groups = "drop")

ggplot(novel_time, aes(x = reorder(Philosophical_View, -Time_Read), y = Time_Read, fill = Philosophical_View)) +
  geom_bar(stat = "identity") +
  theme_minimal() +
  labs(
    title = "Read Time by Philosophical View (Novels Only)",
    x = "Philosophical View",
    y = "Total Read Time"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

# Create a unified Length column
ASL_long <- ASL_unique %>%
  mutate(Length = case_when(
    Short_Story == 1 ~ "Short Story",
    Novelette == 1 ~ "Novelette",
    Novella == 1 ~ "Novella",
    Novel == 1 ~ "Novel",
    Poetry == 1 ~ "Poetry",
    TRUE ~ "Other"
  ))

# List of unique lengths to loop over
lengths <- unique(ASL_long$Length)

# Loop through each length and plot
for (len in lengths) {
  plot_data <- ASL_long %>%
    filter(Length == len) %>%
    group_by(Philosophical_View) %>%
    summarise(Time_Read = sum(Read_Time, na.rm = TRUE), .groups = "drop") %>%
    filter(Time_Read > 0)

  p <- ggplot(plot_data, aes(x = reorder(Philosophical_View, -Time_Read), y = Time_Read, fill = Philosophical_View)) +
    geom_bar(stat = "identity") +
    theme_minimal() +
    labs(
      title = paste("Read Time by Philosophical View (", len, "s)", sep = ""),
      x = "Philosophical View",
      y = "Total Read Time"
    ) +
    theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.position = "none")

  print(p)
}

Personal Significance

# Get top 7 Personal_Significance by total Read_Time
top_significance <- ASL %>%
  group_by(Personal_Significance) %>%
  summarise(TotalReadTime = sum(Read_Time, na.rm = TRUE)) %>%
  arrange(desc(TotalReadTime)) %>%
  slice_head(n = 7) %>%
  pull(Personal_Significance)

# Filter ASL for only these top Personal_Significance categories
filtered_ASL <- ASL %>%
  filter(Personal_Significance %in% top_significance)

# Order Personal_Significance factor by total Read_Time (for x-axis order)
sig_order <- filtered_ASL %>%
  group_by(Personal_Significance) %>%
  summarise(TotalReadTime = sum(Read_Time, na.rm = TRUE)) %>%
  arrange(desc(TotalReadTime)) %>%
  pull(Personal_Significance)

filtered_ASL$Personal_Significance <- factor(filtered_ASL$Personal_Significance, levels = sig_order)

# Plot: x = Personal_Significance, y = Read_Time, fill = Personal_Significance (for legend)
ggplot(filtered_ASL, aes(x = Personal_Significance, y = Read_Time, fill = Personal_Significance)) +
  geom_boxplot(outlier.shape = 21, outlier.alpha = 0.4) +
  coord_flip() +
  labs(
    title = "Time Spent Reading by Personal Significance (Top 7 Categories)",
    x = "Personal Significance",
    y = "Read Time",
    fill = "Personal Significance"
  ) +
  theme_minimal(base_size = 14) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Moral Outlook (simplified)

table(ASL$Moral_Outlook)
## 
##          Absurdist           Admiring   Aesthetic Virtue       Affectionate 
##                  3                  1                  1                  2 
##          Ambiguity          Ambiguous         Carpe Diem         Cautionary 
##                  1                 25                  1                  3 
##   Christian Virtue      Collaborative    Creative Genius Creative Integrity 
##                  1                  1                  1                  1 
##           Critical            Cynical               Dark         Devotional 
##                  2                  7                  3                  6 
##        Educational       Entertaining         Fatalistic               Fear 
##                  5                  5                 10                  1 
##          Grotesque           Haunting            Healing             Heroic 
##                  8                  1                  1                  2 
##            Hopeful         Humanistic         Idealistic               Just 
##                  8                  2                 16                 65 
##        Melancholic              Moral         Moralistic             Morbid 
##                 53                  4                 41                  1 
##          Mortality           Mournful           Mystical         Nihilistic 
##                  4                  6                  1                  4 
##         Optimistic            Playful          Practical          Pragmatic 
##                  2                  1                  1                  8 
##           Rational        Rationalist            Realist         Redemptive 
##                  1                 11                  3                 11 
##         Reflective          Reformist           Reverent      Revolutionary 
##                  6                  1                  1                  1 
##           Romantic          Satirical           Sinister          Spiritual 
##                  4                  2                  2                  3 
##             Subtle             Tragic       Transcendent         Unsettling 
##                 12                  2                  1                  2 
##          Uplifting        Utilitarian        Warmhearted 
##                  3                  3                  1
ASL %>%
  count(Moral_Outlook, sort = TRUE)
## # A tibble: 59 × 2
##    Moral_Outlook     n
##    <chr>         <int>
##  1 Just             65
##  2 Melancholic      53
##  3 Moralistic       41
##  4 Ambiguous        25
##  5 Idealistic       16
##  6 Subtle           12
##  7 Rationalist      11
##  8 Redemptive       11
##  9 Fatalistic       10
## 10 Grotesque         8
## # ℹ 49 more rows
ASL_Moral_Outlook <- ASL %>%
  mutate(Moral_Outlook_Simplified = case_when(
    Moral_Outlook %in% c("Melancholic", "Mournful", "Tragic", "Morbid", "Mortality", "Grotesque", "Nihilistic", "Fatalistic", "Haunting", "Fear", "Unsettling") ~ "Melancholic",
    Moral_Outlook %in% c("Moralistic", "Just", "Devotional", "Christian Virtue", "Moral", "Rationalist", "Utilitarian", "Reverent", "Reformist", "Critical", "Cautionary") ~ "Moralistic",
    Moral_Outlook %in% c("Ambiguous", "Ambiguity", "Dark", "Absurdist", "Reflective", "Cynical", "Realist", "Mystical", "Sinister", "Spiritual") ~ "Ambiguous",
    Moral_Outlook %in% c("Idealistic", "Hopeful", "Romantic", "Humanistic", "Uplifting", "Heroic", "Transcendent", "Optimistic", "Redemptive", "Admiring") ~ "Idealistic",
    Moral_Outlook %in% c("Subtle", "Aesthetic Virtue", "Affectionate", "Healing", "Collaborative", "Creative Genius", "Creative Integrity", "Warmhearted", "Playful") ~ "Subtle",
    TRUE ~ "Other"  # optional fallback
  ))

ASL_Moral_Outlook %>%
  count(Moral_Outlook_Simplified) %>%
  ggplot(aes(x = "", y = n, fill = Moral_Outlook_Simplified)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  labs(title = "Moral Outlook Distribution (Simplified)") +
  theme_void() +
  theme(legend.position = "right")

Era (Box Plot)

ASL %>%
  mutate(Era = reorder(Era, Year_Published)) %>%
  ggplot(aes(x = Era, y = Read_Time, fill = Era)) +
  geom_boxplot() +
  labs(title = "Read Time by Era (Chronologically Ordered)",
       x = "Era", y = "Read Time") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Unique Authors Area

Political Leaning

# Create author_totals by summing read time (or pages) per author & political leaning
author_totals <- ASL_unique %>%
  group_by(Political_Leaning, Author) %>%
  summarise(Total_Read_Time = sum(Read_Time, na.rm = TRUE), .groups = "drop")

# Identify top author per Political_Leaning
top_authors <- author_totals %>%
  group_by(Political_Leaning) %>%
  slice_max(order_by = Total_Read_Time, n = 1, with_ties = FALSE) %>%
  select(Political_Leaning, Author) %>%
  rename(Top_Author = Author)

# Join and flag categories
author_totals_flagged <- author_totals %>%
  left_join(top_authors, by = "Political_Leaning") %>%
  mutate(Category = ifelse(Author == Top_Author, Author, "Other")) %>%
  select(-Top_Author)

# Calculate category order for plotting and legend
category_order <- author_totals_flagged %>%
  group_by(Category) %>%
  summarise(Total_Read_Time = sum(Total_Read_Time, na.rm = TRUE), .groups = "drop") %>%
  arrange(Total_Read_Time) %>%
  pull(Category)

category_order <- c("Other", setdiff(category_order, "Other"))

author_totals_flagged <- author_totals_flagged %>%
  mutate(Category = factor(Category, levels = category_order))

# Set palette colors
n_colors <- length(category_order)
palette_colors <- brewer.pal(min(n_colors, 12), "Set3")
if (n_colors > 12) {
  palette_colors <- colorRampPalette(palette_colors)(n_colors)
}
names(palette_colors) <- category_order

# Aggregate for plotting
plot_data <- author_totals_flagged %>%
  group_by(Political_Leaning, Category) %>%
  summarise(Total_Read_Time = sum(Total_Read_Time, na.rm = TRUE), .groups = "drop")

# Plot
ggplot(plot_data, aes(x = reorder(Political_Leaning, -Total_Read_Time), 
                      y = Total_Read_Time, fill = Category)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = palette_colors) +
  theme_minimal() +
  labs(
    title = "Total Read Time by Political Leaning: Top Author vs Other",
    x = "Political Leaning",
    y = "Total Read Time (minutes)",
    fill = "Category"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  guides(fill = guide_legend(reverse = TRUE))

Education Level

ASL_authors_unique <- ASL_unique %>%
  group_by(Author) %>%
  summarise(
    Political_Leaning = first(Political_Leaning),
    Education_Level = first(Education_Level),
    Era = first(Era),
    Mental_Health = first(Mental_Health),
    Works = n(),
    Total_Read_Time = sum(Read_Time, na.rm = TRUE),
    Avg_Read_Time = round(mean(Read_Time, na.rm = TRUE), 2),
    Total_Pages = sum(Pages, na.rm = TRUE),
    Avg_Pages = round(mean(Pages, na.rm = TRUE), 1),
    Avg_Stars = round(mean(Stars, na.rm = TRUE), 2),
    Five_Stars = sum(Stars == 5, na.rm = TRUE),
    Likeability = round(100 * Five_Stars / Works, 1)
  ) %>%
  arrange(desc(Total_Read_Time))


ASL_authors_unique %>%
  count(Education_Level) %>%
  ggplot(aes(x = factor(Education_Level), y = n)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  theme_minimal() +
  labs(
    title = "Author Count by Education Level",
    x = "Education Level (-1 = No HS, 0 = HS, 2 = Assoc, 4 = BA, 6 = MA, 8 = PhD)",
    y = "Number of Authors"
  )

Mental Health

# Calculate total read time per mental health category
mental_health_summary <- ASL_authors_unique %>%
  group_by(Mental_Health) %>%
  summarise(
    Total_Read_Time = sum(Total_Read_Time, na.rm = TRUE)
  ) %>%
  mutate(
    Percentage = round(100 * Total_Read_Time / sum(Total_Read_Time), 1),
    label = paste0(Mental_Health, " (", Percentage, "%)")
  ) %>%
  arrange(desc(Total_Read_Time)) %>%
  mutate(label = factor(label, levels = label))  # This fixes the legend order

# Plot the pie chart
ggplot(mental_health_summary, aes(x = "", y = Total_Read_Time, fill = label)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  theme_void() +
  theme(
    legend.title = element_blank(),
    legend.position = "right"
  ) +
  guides(fill = guide_legend(reverse = FALSE))