Introduction

For this assignment, I selected Apple (AAPL), Microsoft (MSFT), and Walmart (WMT). I used historical stock data to practice the visualization techniques from Code Along 1.

Load Stock Data

library(tidyverse)
library(tidyquant)

stocks <- tq_get(
  c("AAPL", "MSFT", "WMT"),
  from = "2025-01-01",
  to = "2026-09-01"
)

head(stocks)
## # A tibble: 6 × 8
##   symbol date        open  high   low close   volume adjusted
##   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
## 1 AAPL   2025-01-02  249.  249.  242.  244. 55740700     242.
## 2 AAPL   2025-01-03  243.  244.  242.  243. 40244100     242.
## 3 AAPL   2025-01-06  244.  247.  243.  245  45045600     243.
## 4 AAPL   2025-01-07  243.  246.  241.  242. 40856000     240.
## 5 AAPL   2025-01-08  242.  244.  240.  243. 37628900     241.
## 6 AAPL   2025-01-10  240.  240.  233   237. 61710900     235.

Historical Stock Prices

ggplot(data = stocks,
       mapping = aes(x = date,
                     y = adjusted,
                     color = symbol)) +
  geom_line() +
  labs(
    title = "Apple, Microsoft and Walmart Stock Prices",
    x = "Date",
    y = "Adjusted Closing Price ($)",
    color = "Stock"
  )

Daily Stock Returns

returns <- stocks %>%
  group_by(symbol) %>%
  arrange(date) %>%
  mutate(daily_return = adjusted / lag(adjusted) - 1) %>%
  filter(!is.na(daily_return))

ggplot(data = returns,
       mapping = aes(x = daily_return,
                     fill = symbol)) +
  geom_histogram(bins = 40) +
  facet_wrap(~ symbol) +
  labs(
    title = "Distribution of Daily Stock Returns",
    x = "Daily Return",
    y = "Number of Days",
    fill = "Stock"
  )

Conclusion

My first graph compares the adjusted closing prices of the three stocks over time. My second set of graphs uses scatterplots and smooth trend lines to show each stock separately. Finally, I created histograms to examine the distribution of daily returns.

These graphs demonstrate how ggplot2 can be used to visualize financial data. The return histograms are particularly useful because they show how frequently different daily gains and losses occurred.

Apply the dplyr verbs learned in Chapter 5

Filter rows

# Apple stock prices only
filter(stocks, symbol == "AAPL")
## # A tibble: 416 × 8
##    symbol date        open  high   low close   volume adjusted
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
##  1 AAPL   2025-01-02  249.  249.  242.  244. 55740700     242.
##  2 AAPL   2025-01-03  243.  244.  242.  243. 40244100     242.
##  3 AAPL   2025-01-06  244.  247.  243.  245  45045600     243.
##  4 AAPL   2025-01-07  243.  246.  241.  242. 40856000     240.
##  5 AAPL   2025-01-08  242.  244.  240.  243. 37628900     241.
##  6 AAPL   2025-01-10  240.  240.  233   237. 61710900     235.
##  7 AAPL   2025-01-13  234.  235.  230.  234. 49630700     233.
##  8 AAPL   2025-01-14  235.  236.  232.  233. 39435300     232.
##  9 AAPL   2025-01-15  235.  239.  234.  238. 39832000     236.
## 10 AAPL   2025-01-16  237.  238.  228.  228. 71759100     227.
## # ℹ 406 more rows
# Stock prices from January 2026
filter(stocks, date >= as.Date("2026-01-01"),
       date < as.Date("2026-02-01"))
## # A tibble: 60 × 8
##    symbol date        open  high   low close   volume adjusted
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
##  1 AAPL   2026-01-02  272.  278.  269   271. 37838100     270.
##  2 AAPL   2026-01-05  271.  272.  266.  267. 45647200     267.
##  3 AAPL   2026-01-06  267   268.  262.  262. 52352100     262.
##  4 AAPL   2026-01-07  263.  264.  260.  260. 48309800     260.
##  5 AAPL   2026-01-08  257.  259.  256.  259. 50419300     258.
##  6 AAPL   2026-01-09  259.  260.  256.  259. 39997000     259.
##  7 AAPL   2026-01-12  259.  261.  257.  260. 45263800     260.
##  8 AAPL   2026-01-13  259.  262.  258.  261. 45730800     260.
##  9 AAPL   2026-01-14  259.  262.  257.  260. 40019400     259.
## 10 AAPL   2026-01-15  261.  261.  257.  258. 39388600     258.
## # ℹ 50 more rows
# Apple or Microsoft
filter(stocks, symbol %in% c("AAPL", "MSFT"))
## # A tibble: 832 × 8
##    symbol date        open  high   low close   volume adjusted
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
##  1 AAPL   2025-01-02  249.  249.  242.  244. 55740700     242.
##  2 AAPL   2025-01-03  243.  244.  242.  243. 40244100     242.
##  3 AAPL   2025-01-06  244.  247.  243.  245  45045600     243.
##  4 AAPL   2025-01-07  243.  246.  241.  242. 40856000     240.
##  5 AAPL   2025-01-08  242.  244.  240.  243. 37628900     241.
##  6 AAPL   2025-01-10  240.  240.  233   237. 61710900     235.
##  7 AAPL   2025-01-13  234.  235.  230.  234. 49630700     233.
##  8 AAPL   2025-01-14  235.  236.  232.  233. 39435300     232.
##  9 AAPL   2025-01-15  235.  239.  234.  238. 39832000     236.
## 10 AAPL   2025-01-16  237.  238.  228.  228. 71759100     227.
## # ℹ 822 more rows

Arrange rows

# Highest adjusted closing prices first
arrange(stocks, desc(adjusted))
## # A tibble: 1,248 × 8
##    symbol date        open  high   low close   volume adjusted
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
##  1 MSFT   2025-10-28  550   554.  541.  542. 29986700     538.
##  2 MSFT   2025-10-29  545.  546.  537.  542. 36023000     537.
##  3 MSFT   2025-08-04  528.  538.  528.  536. 25349000     530.
##  4 MSFT   2025-07-31  555.  555.  532.  534. 51617300     528.
##  5 MSFT   2025-10-27  532.  535.  529.  532. 18734700     527.
##  6 MSFT   2025-10-06  519.  531.  518.  529. 21388600     524.
##  7 MSFT   2025-08-12  524.  531.  523.  529. 18667000     524.
##  8 MSFT   2025-08-05  537.  537.  527.  528. 19171600     523.
##  9 MSFT   2025-10-30  530.  535.  522.  526. 41023100     521.
## 10 MSFT   2025-10-08  523.  527.  523.  525. 13363400     521.
## # ℹ 1,238 more rows
# Sort by stock and date
arrange(stocks, symbol, date)
## # A tibble: 1,248 × 8
##    symbol date        open  high   low close   volume adjusted
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
##  1 AAPL   2025-01-02  249.  249.  242.  244. 55740700     242.
##  2 AAPL   2025-01-03  243.  244.  242.  243. 40244100     242.
##  3 AAPL   2025-01-06  244.  247.  243.  245  45045600     243.
##  4 AAPL   2025-01-07  243.  246.  241.  242. 40856000     240.
##  5 AAPL   2025-01-08  242.  244.  240.  243. 37628900     241.
##  6 AAPL   2025-01-10  240.  240.  233   237. 61710900     235.
##  7 AAPL   2025-01-13  234.  235.  230.  234. 49630700     233.
##  8 AAPL   2025-01-14  235.  236.  232.  233. 39435300     232.
##  9 AAPL   2025-01-15  235.  239.  234.  238. 39832000     236.
## 10 AAPL   2025-01-16  237.  238.  228.  228. 71759100     227.
## # ℹ 1,238 more rows

Select columns

# Keep selected columns
select(stocks, symbol, date, adjusted)
## # A tibble: 1,248 × 3
##    symbol date       adjusted
##    <chr>  <date>        <dbl>
##  1 AAPL   2025-01-02     242.
##  2 AAPL   2025-01-03     242.
##  3 AAPL   2025-01-06     243.
##  4 AAPL   2025-01-07     240.
##  5 AAPL   2025-01-08     241.
##  6 AAPL   2025-01-10     235.
##  7 AAPL   2025-01-13     233.
##  8 AAPL   2025-01-14     232.
##  9 AAPL   2025-01-15     236.
## 10 AAPL   2025-01-16     227.
## # ℹ 1,238 more rows
# Keep stock name and price columns
select(stocks, symbol, date, open, close, adjusted)
## # A tibble: 1,248 × 5
##    symbol date        open close adjusted
##    <chr>  <date>     <dbl> <dbl>    <dbl>
##  1 AAPL   2025-01-02  249.  244.     242.
##  2 AAPL   2025-01-03  243.  243.     242.
##  3 AAPL   2025-01-06  244.  245      243.
##  4 AAPL   2025-01-07  243.  242.     240.
##  5 AAPL   2025-01-08  242.  243.     241.
##  6 AAPL   2025-01-10  240.  237.     235.
##  7 AAPL   2025-01-13  234.  234.     233.
##  8 AAPL   2025-01-14  235.  233.     232.
##  9 AAPL   2025-01-15  235.  238.     236.
## 10 AAPL   2025-01-16  237.  228.     227.
## # ℹ 1,238 more rows

Add columns

# Calculate the daily price change
stocks %>%
  group_by(symbol) %>%
  arrange(date, .by_group = TRUE) %>%
  mutate(
    price_change = adjusted - lag(adjusted),
    daily_return = adjusted / lag(adjusted) - 1
  )
## # A tibble: 1,248 × 10
## # Groups:   symbol [3]
##    symbol date        open  high   low close   volume adjusted price_change
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>        <dbl>
##  1 AAPL   2025-01-02  249.  249.  242.  244. 55740700     242.       NA    
##  2 AAPL   2025-01-03  243.  244.  242.  243. 40244100     242.       -0.486
##  3 AAPL   2025-01-06  244.  247.  243.  245  45045600     243.        1.63 
##  4 AAPL   2025-01-07  243.  246.  241.  242. 40856000     240.       -2.77 
##  5 AAPL   2025-01-08  242.  244.  240.  243. 37628900     241.        0.486
##  6 AAPL   2025-01-10  240.  240.  233   237. 61710900     235.       -5.81 
##  7 AAPL   2025-01-13  234.  235.  230.  234. 49630700     233.       -2.43 
##  8 AAPL   2025-01-14  235.  236.  232.  233. 39435300     232.       -1.11 
##  9 AAPL   2025-01-15  235.  239.  234.  238. 39832000     236.        4.56 
## 10 AAPL   2025-01-16  237.  238.  228.  228. 71759100     227.       -9.54 
## # ℹ 1,238 more rows
## # ℹ 1 more variable: daily_return <dbl>

Summarize with groups

# Average adjusted closing price for each stock
stocks %>%
  group_by(symbol) %>%
  summarise(
    avg_price = mean(adjusted, na.rm = TRUE),
    highest_price = max(adjusted, na.rm = TRUE),
    lowest_price = min(adjusted, na.rm = TRUE),
    count = n()
  )
## # A tibble: 3 × 5
##   symbol avg_price highest_price lowest_price count
##   <chr>      <dbl>         <dbl>        <dbl> <int>
## 1 AAPL        252.          340.        171.    416
## 2 MSFT        443.          538.        350.    416
## 3 WMT         107.          134.         80.7   416