knitr::opts_chunk$set(echo = TRUE)

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.4.0      ✔ purrr   1.0.1 
## ✔ tibble  3.1.8      ✔ dplyr   1.0.10
## ✔ tidyr   1.3.0      ✔ stringr 1.5.0 
## ✔ readr   2.1.3      ✔ forcats 1.0.0 
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(ggplot2)

# create datasets

bowling_scores <- read.csv("bowling_scores.csv")

connor_data <- filter(bowling_scores, player == "connor")

seth_data <- filter(bowling_scores, player == "seth")

rebecca_data <- filter(bowling_scores, player == "rebecca")

garrett_data <- filter(bowling_scores, player == "garrett")


# full bowling graph

ggplot(bowling_scores, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = 1) + 
  geom_point(size = 1.5) +
   geom_text(aes(label = format(score)), 
            hjust = -0.1, vjust = -0.5, size = 3, check_overlap = TRUE) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  theme_minimal()  
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.

# find extrema points
find_local_extrema <- function(df) {
  df %>%
    group_by(player) %>%
    mutate(
      local_max = score == max(score),    # Identify local maximum
      local_min = score == min(score)     # Identify local minimum
    ) %>%
    filter(local_max | local_min)         # Keep only max or min points
  }

extrema_points <- find_local_extrema(bowling_scores)

print(extrema_points)
## # A tibble: 29 × 9
## # Groups:   player [15]
##     game  date player  score round splits strikes local_max local_min
##    <int> <dbl> <chr>   <int> <int>  <int> <chr>   <lgl>     <lgl>    
##  1     2  5.24 daniel    102     2      1 ""      TRUE      FALSE    
##  2     2  5.24 emilee     51     2      0 ""      FALSE     TRUE     
##  3     6  5.29 daniel     48     2      1 ""      FALSE     TRUE     
##  4     6  5.29 rebecca    32     2      0 ""      FALSE     TRUE     
##  5     7  5.3  derek      65     1      0 ""      FALSE     TRUE     
##  6     8  5.3  derek      90     2      0 ""      TRUE      FALSE    
##  7     8  5.3  kiana     125     2      1 ""      TRUE      FALSE    
##  8    13  6.03 rebecca   128     2      2 ""      TRUE      FALSE    
##  9    16  6.08 wyatt     129     1      0 ""      TRUE      FALSE    
## 10    16  6.08 kiana      73     1      1 ""      FALSE     TRUE     
## # ℹ 19 more rows
# bowling graph with extrema labels only
ggplot(bowling_scores, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = .9) + 
  geom_point(size = 1) +
    geom_text(data = extrema_points, aes(label = score), vjust = -.25, hjust = -.25, size = 2.5) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  theme_minimal() 

# average scores by player

average_scores <- bowling_scores %>%
  group_by(player) %>%
  summarize(average_score = mean(score))

print(average_scores)
## # A tibble: 15 × 2
##    player  average_score
##    <chr>           <dbl>
##  1 anika            68  
##  2 connor          132. 
##  3 daniel           74  
##  4 derek            77.5
##  5 elaine           68  
##  6 emilee           84.3
##  7 garrett          41  
##  8 kiana            97.8
##  9 neha             58  
## 10 noah            103. 
## 11 quynh            87.5
## 12 rebecca          74.6
## 13 rishabh         103  
## 14 seth             95.3
## 15 wyatt           114.
# average scores by player by round

average_scores_by_round <- bowling_scores %>%
  group_by(player, round) %>%
  summarize(average_score = mean(score)) %>%
  ungroup()
## `summarise()` has grouped output by 'player'. You can override using the
## `.groups` argument.
print(average_scores_by_round)
## # A tibble: 32 × 3
##    player round average_score
##    <chr>  <int>         <dbl>
##  1 anika      1          68  
##  2 connor     1         130. 
##  3 connor     2         134. 
##  4 connor     3         125  
##  5 connor     4         131  
##  6 daniel     1          73.3
##  7 daniel     2          75  
##  8 derek      1          65  
##  9 derek      2          90  
## 10 elaine     1          81  
## # ℹ 22 more rows
# average splits

average_splits <- bowling_scores %>%
  group_by(player) %>%
  summarize(average_splits = mean(splits, na.rm = T))

print(average_splits)
## # A tibble: 15 × 2
##    player  average_splits
##    <chr>            <dbl>
##  1 anika            1    
##  2 connor           0.962
##  3 daniel           1.2  
##  4 derek            0    
##  5 elaine           1.67 
##  6 emilee           1.09 
##  7 garrett          0.833
##  8 kiana            1.75 
##  9 neha             0    
## 10 noah             1    
## 11 quynh            1.38 
## 12 rebecca          0.961
## 13 rishabh          0.75 
## 14 seth             0.5  
## 15 wyatt            0.5
# average score by number of splits

average_score_split <- bowling_scores %>%
  group_by(splits) %>%
  summarize(average_score = mean(score))

print(average_score_split)
## # A tibble: 7 × 2
##   splits average_score
##    <int>         <dbl>
## 1      0          93.5
## 2      1          97.4
## 3      2          89.3
## 4      3          80.7
## 5      4         101  
## 6      5          98  
## 7     NA         154.
#overall average score

overall_avg <- mean(bowling_scores$score)

print(overall_avg)
## [1] 95.18056
# linear model, score as a function of splits 

summary(lm(score ~ splits, data = bowling_scores))
## 
## Call:
## lm(formula = score ~ splits, data = bowling_scores)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -63.292 -21.648  -3.108  25.168  77.076 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   95.292      2.923   32.60   <2e-16 ***
## splits        -1.368      2.243   -0.61    0.543    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 30.9 on 210 degrees of freedom
##   (4 observations deleted due to missingness)
## Multiple R-squared:  0.001768,   Adjusted R-squared:  -0.002986 
## F-statistic: 0.3719 on 1 and 210 DF,  p-value: 0.5426
# score by splits scatterplot (color = player)

ggplot(bowling_scores, aes(x= splits, y=score, color = player)) +
  geom_point()
## Warning: Removed 4 rows containing missing values (`geom_point()`).

# score by splits scatterplot with best fit line
  
ggplot(bowling_scores, aes(x= splits, y=score)) +
  geom_point() +
  geom_smooth(method = "lm")
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 4 rows containing non-finite values (`stat_smooth()`).
## Warning: Removed 4 rows containing missing values (`geom_point()`).

#scores histogram

ggplot(bowling_scores, aes(x = score, color = player)) +
  geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

#score by game scatterplot with best fit line
ggplot(bowling_scores, aes(x= game, y=score)) +
  geom_point() +
  geom_smooth(method = "lm")
## `geom_smooth()` using formula = 'y ~ x'

#score by game linear model
summary(lm(score ~ game, data = bowling_scores))
## 
## Call:
## lm(formula = score ~ game, data = bowling_scores)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -65.323 -23.737  -3.016  22.415  83.819 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  84.0967     4.2217  19.920  < 2e-16 ***
## game          0.3742     0.1231   3.039  0.00267 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 31.25 on 214 degrees of freedom
## Multiple R-squared:  0.04137,    Adjusted R-squared:  0.03689 
## F-statistic: 9.236 on 1 and 214 DF,  p-value: 0.002669
# mean score by game
mean_by_game <- bowling_scores %>%
  group_by(game) %>%
  summarize(mean_score = mean(score))

print(mean_by_game)
## # A tibble: 65 × 2
##     game mean_score
##    <int>      <dbl>
##  1     1       75.4
##  2     2       75.4
##  3     3       61  
##  4     4       73  
##  5     5       88.8
##  6     6       73.8
##  7     7       87.4
##  8     8      110. 
##  9     9      101  
## 10    10       99  
## # ℹ 55 more rows
# overall bowling graph with adaptive mean line
ggplot(bowling_scores, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = 1) + 
  geom_point(size = 1.5) +
   geom_text(aes(label = format(score)), 
            hjust = -0.1, vjust = -0.5, size = 3, check_overlap = TRUE) +
  geom_hline(yintercept = overall_avg, linetype = "dashed", color = "red", size = 1) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  theme_minimal()  

# number of games played by player
games_played <- bowling_scores %>%
  group_by(player) %>%
  summarize(num_games = n())

print(games_played)
## # A tibble: 15 × 2
##    player  num_games
##    <chr>       <int>
##  1 anika           1
##  2 connor         56
##  3 daniel          5
##  4 derek           2
##  5 elaine          3
##  6 emilee         11
##  7 garrett        12
##  8 kiana           8
##  9 neha            1
## 10 noah            4
## 11 quynh           8
## 12 rebecca        51
## 13 rishabh         4
## 14 seth           48
## 15 wyatt           2
#connor graph

ggplot(connor_data, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = 1) + 
  geom_point(size = 1.5) +
   geom_text(aes(label = format(score)), 
            hjust = -0.1, vjust = -0.5, size = 3, check_overlap = TRUE) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  geom_smooth() +
  theme_minimal()  
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

ggplot(connor_data, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = 1) + 
  geom_point(size = 1.5) +
   geom_text(aes(label = format(score)), 
            hjust = -0.1, vjust = -0.5, size = 3, check_overlap = TRUE) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  geom_smooth(method = "lm") +
  theme_minimal()  
## `geom_smooth()` using formula = 'y ~ x'

# rebecca graph
ggplot(rebecca_data, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = 1) + 
  geom_point(size = 1.5) +
   geom_text(aes(label = format(score)), 
            hjust = -0.1, vjust = -0.5, size = 3, check_overlap = TRUE) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  geom_smooth() +
  theme_minimal()  
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

ggplot(rebecca_data, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = 1) + 
  geom_point(size = 1.5) +
   geom_text(aes(label = format(score)), 
            hjust = -0.1, vjust = -0.5, size = 3, check_overlap = TRUE) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  geom_smooth(method = "lm") +
  theme_minimal()  
## `geom_smooth()` using formula = 'y ~ x'

# my graph

ggplot(seth_data, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = 1) + 
  geom_point(size = 1.5) +
   geom_text(aes(label = format(score)), 
            hjust = -0.1, vjust = -0.5, size = 3, check_overlap = TRUE) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  geom_smooth() +
  theme_minimal()  
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

ggplot(seth_data, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = 1) + 
  geom_point(size = 1.5) +
   geom_text(aes(label = format(score)), 
            hjust = -0.1, vjust = -0.5, size = 3, check_overlap = TRUE) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  geom_smooth(method = "lm") +
  theme_minimal()  
## `geom_smooth()` using formula = 'y ~ x'

ggplot(garrett_data, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = 1) + 
  geom_point(size = 1.5) +
   geom_text(aes(label = format(score)), 
            hjust = -0.1, vjust = -0.5, size = 3, check_overlap = TRUE) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  geom_smooth() +
  theme_minimal()  
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

## real ones only graph
bowling_scores_lil <- bowling_scores %>%
  filter(player %in% c("seth", "connor", "rebecca", "emilee", "garrett"))

ggplot(bowling_scores_lil, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = .9) + 
  geom_point(size = 1) +
   geom_text(aes(label = format(score)), 
            hjust = -0.1, vjust = -0.5, size = 2.5, check_overlap = TRUE) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  theme_minimal()  +
  geom_smooth(method = lm, se = FALSE, linetype = "dashed", size = 1)
## `geom_smooth()` using formula = 'y ~ x'

find_local_extrema <- function(df) {
  df %>%
    group_by(player) %>%
    mutate(
      local_max = score == max(score),    # Identify local maximum
      local_min = score == min(score)     # Identify local minimum
    ) %>%
    filter(local_max | local_min)         # Keep only max or min points
  }

extrema_points_lil <- find_local_extrema(bowling_scores_lil)

ggplot(bowling_scores_lil, aes(x = game, y = score, color = player, group = player)) +
  geom_line(size = .9) + 
  geom_point(size = 1) +
    geom_text(data = extrema_points_lil, aes(label = score), vjust = -.25, hjust = -.25, size = 2.5) +
  labs(title = "Bowling Scores Summer 2K24",
       x = "Game",
       y = "Score") +
  theme_minimal()  +
  geom_smooth(method = lm, se = FALSE, linetype = "dashed", size = 1)
## `geom_smooth()` using formula = 'y ~ x'