```{r setup, include=FALSE} # Global options knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE)

Install packages if missing

if (!require(“tidyverse”)) install.packages(“tidyverse”) if (!require(“plotly”)) install.packages(“plotly”) if (!require(“DT”)) install.packages(“DT”)

Load libraries

library(tidyverse) library(plotly) library(DT) # 1. Define the raw data raw_data <- “Symbol,Company,Sector,PE_Current,ROE_2020,ROE_2021,ROE_2022,ROE_2023,ROE_2024,EPS_2020,EPS_2021,EPS_2022,EPS_2023,EPS_2024 AAPL,Apple Inc.,Technology,28.5,0.73,0.85,1.20,1.35,1.45,3.20,4.50,5.60,6.10,6.50 MSFT,Microsoft Corp.,Technology,35.2,0.35,0.38,0.40,0.42,0.44,5.10,6.20,8.05,9.60,11.10 AMZN,Amazon.com Inc.,Consumer Disc.,75.0,0.20,0.22,0.05,0.12,0.15,1.15,2.10,0.50,1.50,2.80 GOOGL,Alphabet Inc.,Technology,24.5,0.18,0.25,0.22,0.24,0.27,2.80,4.10,4.50,5.20,6.10 TSLA,Tesla Inc.,Consumer Disc.,68.5,0.05,0.15,0.25,0.20,0.21,0.25,0.80,1.90,2.40,3.10 JPM,JPMorgan Chase,Financials,11.5,0.12,0.15,0.14,0.16,0.17,8.50,10.10,11.50,12.80,14.50 JNJ,Johnson & Johnson,Health Care,15.8,0.22,0.24,0.23,0.25,0.26,6.50,7.10,7.50,8.10,8.50 PG,Procter & Gamble,Consumer Staples,24.5,0.28,0.29,0.30,0.31,0.32,4.80,5.10,5.40,5.90,6.40 XOM,Exxon Mobil,Energy,10.2,-0.05,0.08,0.25,0.20,0.18,-0.50,3.50,8.10,7.20,6.80 NVDA,NVIDIA Corp.,Technology,95.0,0.25,0.35,0.45,0.55,0.65,0.80,1.20,2.50,4.10,8.50 PFE,Pfizer Inc.,Health Care,12.5,0.15,0.22,0.35,0.18,0.15,2.10,3.50,5.80,2.90,2.40 KO,Coca-Cola Co.,Consumer Staples,21.5,0.35,0.38,0.40,0.42,0.45,1.80,2.05,2.20,2.50,2.80 HD,Home Depot,Consumer Disc.,22.5,0.45,0.50,0.55,0.52,0.50,10.20,11.50,13.20,14.10,15.20 BAC,Bank of America,Financials,10.8,0.08,0.11,0.12,0.11,0.10,2.10,2.80,3.20,3.10,3.30 VZ,Verizon Comm.,Communication,8.5,0.25,0.28,0.26,0.25,0.24,4.10,4.80,5.10,5.00,4.90 CSCO,Cisco Systems,Technology,13.5,0.28,0.29,0.30,0.29,0.28,2.80,3.00,3.20,3.50,3.60 INTC,Intel Corp.,Technology,85.0,0.22,0.25,0.15,0.01,-0.05,4.50,5.10,2.50,0.10,-0.50 DIS,Walt Disney,Communication,45.0,-0.02,0.02,0.05,0.08,0.12,-0.80,0.50,1.80,3.20,4.50 NFLX,Netflix Inc.,Communication,42.5,0.25,0.28,0.22,0.25,0.28,5.10,7.50,9.10,10.50,12.80 BA,Boeing Co.,Industrials,NA,-0.50,-0.40,-0.25,-0.10,-0.05,-15.00,-12.00,-8.00,-4.00,-2.50”

2. Read the data

df_wide <- read.csv(text = raw_data, stringsAsFactors = FALSE)

3. Calculate Growth Metrics

df_wide <- df_wide %>% mutate( # Logic: Growing if 2024 EPS > 2020 EPS Growth_Status = ifelse(EPS_2024 > EPS_2020, “Growing”, “Declining”), # Calculate % Growth EPS_Growth_Pct = round(((EPS_2024 - EPS_2020) / abs(EPS_2020)) * 100, 1), # Create Tooltip for interactive plots Tooltip = paste0(“”, Company, “”, “:”, Symbol, “:”, EPS_Growth_Pct, “%”, “/E:”, PE_Current) )

4. Pivot ROE columns to “Long” format for trend plotting

df_long_roe <- df_wide %>% pivot_longer( cols = starts_with(“ROE_”), names_to = “Year_Str”, values_to = “ROE” ) %>% mutate(Year = as.numeric(gsub(“ROE_”, ““, Year_Str)))

Preview the prepared data

head(df_wide %>% select(Symbol, Company, PE_Current, EPS_Growth_Pct, Growth_Status)) # Create Base Plot p_scatter <- ggplot(df_wide, aes(x = EPS_Growth_Pct, y = PE_Current)) + geom_point(aes(color = Growth_Status, text = Tooltip), size = 3.5, alpha = 0.8) +

# Add reference lines geom_hline(yintercept = mean(df_wide$PE_Current, na.rm = TRUE), linetype=“dashed”, color=“gray60”) + geom_vline(xintercept = 0, linetype=“dashed”, color=“gray60”) +

# Custom Colors scale_color_manual(values = c(“Declining” = “#e74c3c”, “Growing” = “#2ecc71”)) +

# Styling theme_light() + labs(title = “S&P 500: P/E Ratio vs. 5-Year Earnings Growth”, subtitle = “Dashed lines represent Market Average P/E and 0% Growth”, x = “5-Year EPS Growth (%)”, y = “Current P/E Ratio”, color = “Status”)

Convert to Interactive Plot

ggplotly(p_scatter, tooltip = “text”) # Faceted Plot for Small Multiples ggplot(df_long_roe, aes(x = Year, y = ROE, group = Company)) + geom_line(color = “#2c3e50”, linewidth = 1) + geom_point(color = “#18bc9c”, size = 1.5) +

# Create a separate mini-chart for each company facet_wrap(~Company, scales = “free_y”, ncol = 4) +

# Styling theme_minimal() + labs(title = “5-Year ROE Trajectories (2020-2024)”, y = “Return on Equity (ROE)”, x = ““) + theme(strip.text = element_text(face =”bold”, size = 8), axis.text.x = element_text(angle = 45, hjust = 1, size = 7), panel.grid.minor = element_blank()) # Select columns to display display_table <- df_wide %>% select(Symbol, Company, Sector, PE_Current, EPS_Growth_Pct, Growth_Status, EPS_2024)

Render interactive table

datatable(display_table, options = list(pageLength = 10, scrollX = TRUE), rownames = FALSE, class = ‘cell-border stripe’)x