stats <- read.csv("~/Desktop/stats/archive (3)/NBA Player Stats(1950 - 2022).csv")
salaries <- read.csv("~/Desktop/stats/archive (3)/NBA Salaries(1990-2023).csv")

#Cleaning and Merging the Data into one Dataset

# convert salary from text to in millions
# comparable salaries
salaries$salary <- as.numeric(gsub("[$,]", "", salaries$inflationAdjSalary)) / 1000000

# Salaries file uses the year the season started, stats file uses the year it ended
# Add 1 so the seasons match
salaries$Season <- salaries$seasonStartYear + 1

# Salary data starts in 1990, so drop older seasons from the stats file
stats <- stats[stats$Season >= 1991, ]

# Players traded mid-season have one row per team plus a "TOT" (total) row
# Keep only the TOT row for those players so each player-season appears once
key <- paste(stats$Player, stats$Season)
traded <- key[stats$Tm == "TOT"]
stats <- stats[!(key %in% traded) | stats$Tm == "TOT", ]
#remove duplicate player-seasons
salaries <- salaries[!duplicated(salaries[, c("playerName", "Season")]), ]

# Merge files by player name and season
nba <- merge(stats, salaries[, c("playerName", "Season", "salary")],
             by.x = c("Player", "Season"), by.y = c("playerName", "Season"))

# check
nrow(nba)
## [1] 13018

#Part A: Descriptive Statistics: ## 1: Categorical Variable: Position

# players w two positions, keep primary
nba$Position <- sub("-.*", "", nba$Pos)

#pos order alph. 
nba$Position <- factor(nba$Position, levels = c("PG", "SG", "SF", "PF", "C"))

#freq table
pos_freq <- table(nba$Position)
pos_freq
## 
##   PG   SG   SF   PF    C 
## 2507 2684 2426 2784 2617
# relative frequency (prop of player-seasons at each position)
round(prop.table(pos_freq), 3)
## 
##    PG    SG    SF    PF     C 
## 0.193 0.206 0.186 0.214 0.201
# bar chart
barplot(pos_freq,
        main = "Player-Seasons by Position (1991-2022)",
        xlab = "Position", ylab = "Number of Player-Seasons",
        col = "navy")

## 2: Quantitative Variable: Salary

# Descriptive statistics for salary (in millions)
min(nba$salary)
## [1] 0.008074
median(nba$salary)
## [1] 2.947918
max(nba$salary)
## [1] 61.25856
mean(nba$salary)
## [1] 5.607961
sd(nba$salary)
## [1] 6.894125
# Range = max - min
max(nba$salary) - min(nba$salary)
## [1] 61.25048
# histogram
hist(nba$salary,
     breaks = 30,
     main = "Distribution of NBA Salaries (1991-2022)",
     xlab = "Salary (millions, inflation-adjusted $)",
     col = "gold")

## 3: Salary by Position

# Split salary group for each position
pg <- nba$salary[nba$Position == "PG"]
sg <- nba$salary[nba$Position == "SG"]
sf <- nba$salary[nba$Position == "SF"]
pf <- nba$salary[nba$Position == "PF"]
c_ <- nba$salary[nba$Position == "C"]  

# Table --> descript stats
salary_table <- data.frame(
  Position = c("PG", "SG", "SF", "PF", "C"),
  n        = c(length(pg), length(sg), length(sf), length(pf), length(c_)),
  Min      = c(min(pg), min(sg), min(sf), min(pf), min(c_)),
  Median   = c(median(pg), median(sg), median(sf), median(pf), median(c_)),
  Max      = c(max(pg), max(sg), max(sf), max(pf), max(c_)),
  Mean     = c(mean(pg), mean(sg), mean(sf), mean(pf), mean(c_)),
  SD       = c(sd(pg), sd(sg), sd(sf), sd(pf), sd(c_))
)
salary_table$Range <- salary_table$Max - salary_table$Min

# round
salary_table[, -1] <- round(salary_table[, -1], 2)
salary_table
##   Position    n  Min Median   Max Mean   SD Range
## 1       PG 2507 0.03   2.63 49.93 5.28 7.18 49.90
## 2       SG 2684 0.01   2.68 61.26 5.18 6.51 61.25
## 3       SF 2426 0.01   2.84 41.93 5.35 6.51 41.91
## 4       PF 2784 0.01   3.08 46.10 5.89 7.04 46.09
## 5        C 2617 0.03   3.53 44.91 6.31 7.12 44.88
#boxplot 
boxplot(salary ~ Position, data = nba,
        main = "Salary by Position",
        xlab = "Position", ylab = "Salary (millions$)",
        col = "blue")

#Part B: Confidence Interval:

# points conf interval
t.test(stats$PTS, conf.level = 0.95)
## 
##  One Sample t-test
## 
## data:  stats$PTS
## t = 131.3, df = 14706, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  504.9807 520.2865
## sample estimates:
## mean of x 
##  512.6336
# assists conf interval
t.test(stats$AST, conf.level = 0.95)
## 
##  One Sample t-test
## 
## data:  stats$AST
## t = 102.37, df = 14706, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  112.1022 116.4789
## sample estimates:
## mean of x 
##  114.2905
# conf in by position

library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
position_stats = stats %>%
  filter(Pos %in% c("PG", "SG", "SF", "PF", "C")) %>%
  group_by(Pos) %>%
  summarise(
    n = sum(!is.na(PTS)),
    mean = mean(PTS, na.rm = TRUE),
    sd = sd(PTS, na.rm = TRUE),
    SE = sd / sqrt(n),
    lower_CI = mean - qt(0.975, df = n - 1) * SE,
    upper_CI = mean + qt(0.975, df = n - 1) * SE
  )

position_stats
## # A tibble: 5 × 7
##   Pos       n  mean    sd    SE lower_CI upper_CI
##   <chr> <int> <dbl> <dbl> <dbl>    <dbl>    <dbl>
## 1 C      2974  421.  421.  7.71     406.     436.
## 2 PF     3024  504.  470.  8.55     487.     521.
## 3 PG     2829  536.  467.  8.78     518.     553.
## 4 SF     2677  549.  489.  9.45     531.     568.
## 5 SG     2966  565.  510.  9.37     547.     584.