Answer.
For this discussion, I use two datasets. The first dataset is my
fantasy football one-year point projection dataset. The second dataset
is AirPassengers, a time series dataset included in base
R.
\[ \text{Dataset 1} = \text{Fantasy football player-season projection data} \]
\[ \text{Dataset 2} = \text{AirPassengers monthly passenger data} \]
Answer.
The fantasy football dataset contains player-season observations used
to study future fantasy football production. Each row represents one NFL
player in one season, with variables such as player_id,
player_name, season, position,
prior fantasy production, weighted multi-year production, and
target-season PPR fantasy points.
\[ \text{Observation unit} = \text{one player in one NFL season} \]
ff_overview <- ff %>%
summarise(
rows = n(),
columns = ncol(.),
unique_players = n_distinct(player_id),
seasons = n_distinct(season),
min_season = min(season, na.rm = TRUE),
max_season = max(season, na.rm = TRUE)
)
kable(ff_overview)
| rows | columns | unique_players | seasons | min_season | max_season |
|---|---|---|---|---|---|
| 6293 | 279 | 1713 | 24 | 2002 | 2025 |
ff %>%
select(
player_id,
player_name,
season,
position,
lag1_fantasy_points_ppr,
weighted_3yr_fantasy_points_ppr,
target_fantasy_points_ppr
) %>%
head(10) %>%
kable()
| player_id | player_name | season | position | lag1_fantasy_points_ppr | weighted_3yr_fantasy_points_ppr | target_fantasy_points_ppr |
|---|---|---|---|---|---|---|
| 00-0005741 | Rich Gannon | 2002 | QB | 266.22 | 271.564 | 303.16 |
| 00-0003739 | Daunte Culpepper | 2002 | QB | 201.08 | 222.456 | 285.02 |
| 00-0020245 | Mike Vick | 2002 | QB | 58.30 | 34.980 | 279.14 |
| 00-0010346 | Peyton Manning | 2002 | QB | 260.94 | 269.718 | 264.80 |
| 00-0001823 | Aaron Brooks | 2002 | QB | 253.08 | 185.076 | 256.18 |
| 00-0006355 | Trent Green | 2002 | QB | 188.22 | 155.886 | 256.10 |
| 00-0011024 | Steve McNair | 2002 | QB | 265.40 | 230.902 | 253.48 |
| 00-0001361 | Drew Bledsoe | 2002 | QB | 21.80 | 90.470 | 251.06 |
| 00-0005755 | Jeff Garcia | 2002 | QB | 296.92 | 295.652 | 251.06 |
| 00-0019596 | Tom Brady | 2002 | QB | 163.32 | 98.064 | 245.56 |
The selected columns show the basic structure of the dataset. The player and season columns identify the unit and time period, while the fantasy point columns describe past and target-season performance.
\[ FantasyPoints_{i,t} = \text{fantasy points for player } i \text{ in season } t \]
Answer.
I would classify the fantasy football dataset as an unbalanced panel dataset. It is panel data because it tracks players across multiple seasons, meaning the data have both an individual identifier and a time identifier.
\[ i = \text{player} \]
\[ t = \text{season} \]
\[ \text{Panel observation} = (i,t) \]
It is unbalanced because not every player appears in every season. Some players enter the league, retire, miss seasons, or are not included in the fantasy-relevant sample every year.
player_season_counts <- ff %>%
count(player_id, player_name, name = "seasons_observed") %>%
arrange(desc(seasons_observed))
panel_summary <- data.frame(
Metric = c(
"Number of seasons",
"Number of unique players",
"Maximum seasons observed for one player",
"Data type classification"
),
Value = c(
n_distinct(ff$season),
n_distinct(ff$player_id),
max(player_season_counts$seasons_observed),
"Unbalanced panel data"
)
)
kable(panel_summary)
| Metric | Value |
|---|---|
| Number of seasons | 24 |
| Number of unique players | 1713 |
| Maximum seasons observed for one player | 20 |
| Data type classification | Unbalanced panel data |
The table above supports the panel-data classification because the dataset includes many players observed across many seasons.
top_players <- player_season_counts %>%
slice_head(n = 6)
player_season_table <- ff %>%
semi_join(top_players, by = c("player_id", "player_name")) %>%
mutate(observed = 1) %>%
distinct(player_name, season, observed) %>%
pivot_wider(
names_from = season,
values_from = observed,
values_fill = 0
)
kable(player_season_table)
| player_name | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2024 | 2025 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Tom Brady | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 |
| Drew Brees | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
| Jason Witten | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
| Ben Roethlisberger | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 |
| Larry Fitzgerald | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
| Aaron Rodgers | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
The player-by-season table shows repeated observations for the same players across different years. That repeated structure is the key reason this is panel data rather than simple cross-sectional data.
The chart is useful descriptively because it shows how the target fantasy point outcome differs by position. This is not what makes the data panel data, but it helps describe the cross-sectional player-position differences within the dataset.
Answer.
The AirPassengers dataset contains monthly totals of
international airline passengers from 1949 through 1960. The main
variable is passenger count, and each observation represents one
month.
\[ \text{Observation unit} = \text{one monthly passenger count} \]
data(AirPassengers)
AirPassengers
## Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
## 1949 112 118 132 129 121 135 148 148 136 119 104 118
## 1950 115 126 141 135 125 149 170 170 158 133 114 140
## 1951 145 150 178 163 172 178 199 199 184 162 146 166
## 1952 171 180 193 181 183 218 230 242 209 191 172 194
## 1953 196 196 236 235 229 243 264 272 237 211 180 201
## 1954 204 188 235 227 234 264 302 293 259 229 203 229
## 1955 242 233 267 269 270 315 364 347 312 274 237 278
## 1956 284 277 317 313 318 374 413 405 355 306 271 306
## 1957 315 301 356 348 355 422 465 467 404 347 305 336
## 1958 340 318 362 348 363 435 491 505 404 359 310 337
## 1959 360 342 406 396 420 472 548 559 463 407 362 405
## 1960 417 391 419 461 472 535 622 606 508 461 390 432
start(AirPassengers)
## [1] 1949 1
end(AirPassengers)
## [1] 1960 12
frequency(AirPassengers)
## [1] 12
summary(AirPassengers)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 104.0 180.0 265.5 280.3 360.5 622.0
Answer.
I would classify AirPassengers as time series
data because it records the same variable repeatedly over time.
The order of the observations matters because the passenger counts
follow a chronological monthly sequence.
\[ \text{Time series data} = \{y_t: t = 1,2,3,\dots,T\} \]
In this dataset:
\[ y_t = \text{international airline passengers in month } t \]
plot(
AirPassengers,
main = "Monthly International Airline Passengers, 1949-1960",
xlab = "Year",
ylab = "Passengers"
)
The time plot shows both an upward trend and a seasonal pattern. This
differs from the fantasy football panel dataset because
AirPassengers follows one variable through time, while the
fantasy football dataset follows many players across seasons.
Answer.
Covariance measures how two variables move together. If higher values of one variable tend to occur with higher values of another variable, covariance is positive. If higher values of one variable tend to occur with lower values of another variable, covariance is negative.
\[ Cov(x,y) = \frac{\sum_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})}{n - 1} \]
In this fantasy football example, covariance tells us whether players with higher previous-season PPR fantasy points also tend to have higher target-season PPR fantasy points.
\[ Cov(\text{Lag1 PPR Points}, \text{Target PPR Points}) \]
Answer.
Variance measures how spread out one variable is around its own mean. A variable with high variance has values that are more spread out, while a variable with low variance has values that are closer to the average.
\[ Var(x) = \frac{\sum_{i=1}^{n}(x_i - \bar{x})^2}{n - 1} \]
In this example, the variance of previous-season fantasy points tells us how much prior fantasy production differs across players.
\[ Var(\text{Lag1 PPR Points}) \]
Answer.
In simple linear regression, the slope measures the average change in the dependent variable for a one-unit increase in the independent variable. Covariance measures the shared movement between \(x\) and \(y\), while variance measures how much \(x\) moves on its own. Dividing covariance by variance rescales the shared movement into a per-one-unit change in \(x\).
\[ \hat{\beta}_1 = \frac{Cov(y,x)}{Var(x)} \]
For the fantasy football regression, this means the slope estimates how much target-season PPR fantasy points change, on average, when previous-season PPR fantasy points increase by one point.
\[ \hat{\beta}_1 = \frac{ Cov(\text{Target PPR Points}, \text{Lag1 PPR Points}) }{ Var(\text{Lag1 PPR Points}) } \]
This formula works for simple linear regression with one independent variable. With multiple independent variables, the coefficient formula becomes more complicated because the model must separate the effect of one predictor from the effects of the others.
Answer.
I use the fantasy football dataset for this regression. The dependent variable is target-season PPR fantasy points, and the independent variable is previous-season PPR fantasy points.
\[ y = \text{target_fantasy_points_ppr} \]
\[ x = \text{lag1_fantasy_points_ppr} \]
The simple regression is:
\[ TargetPPRPoints_i = \beta_0 + \beta_1 Lag1PPRPoints_i + \epsilon_i \]
reg_df <- ff %>%
transmute(
y = target_fantasy_points_ppr,
x = lag1_fantasy_points_ppr
) %>%
filter(!is.na(y), !is.na(x)) %>%
filter(is.finite(y), is.finite(x))
summary(reg_df)
## y x
## Min. : -0.9 Min. : -3.38
## 1st Qu.: 63.8 1st Qu.: 50.05
## Median :117.1 Median :110.80
## Mean :133.5 Mean :124.99
## 3rd Qu.:190.3 3rd Qu.:187.93
## Max. :481.1 Max. :481.10
reg1 <- lm(y ~ x, data = reg_df)
summary(reg1)
##
## Call:
## lm(formula = y ~ x, data = reg_df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -171.57 -43.86 -9.55 36.26 356.03
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 54.495028 1.390374 39.20 <2e-16 ***
## x 0.632367 0.009027 70.05 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 63.61 on 6129 degrees of freedom
## Multiple R-squared: 0.4446, Adjusted R-squared: 0.4445
## F-statistic: 4907 on 1 and 6129 DF, p-value: < 2.2e-16
The slope from the regression output is:
\[ \hat{\beta}_{1,lm} = \text{slope from the } lm() \text{ regression} \]
slope_from_regression <- unname(coef(reg1)["x"])
slope_from_regression
## [1] 0.6323665
Now I calculate the same slope using the covariance-variance formula:
\[ \hat{\beta}_{1,formula} = \frac{Cov(y,x)}{Var(x)} \]
slope_from_formula <- cov(reg_df$y, reg_df$x) / var(reg_df$x)
slope_from_formula
## [1] 0.6323665
The two values match:
\[ \hat{\beta}_{1,lm} = \hat{\beta}_{1,formula} \]
slope_comparison <- data.frame(
Method = c("Regression output", "Covariance divided by variance"),
Slope = c(slope_from_regression, slope_from_formula)
)
kable(slope_comparison)
| Method | Slope |
|---|---|
| Regression output | 0.6323665 |
| Covariance divided by variance | 0.6323665 |
## `geom_smooth()` using formula = 'y ~ x'
The slope is positive, which means that players with higher previous-season PPR fantasy production tend to have higher target-season PPR fantasy production. In this dataset, the estimated slope is approximately 0.63, so a one-point increase in previous-season PPR fantasy points is associated with about a 0.63-point increase in target-season PPR fantasy points, on average.
\[ \text{Estimated slope} \approx 0.63 \]
\[ \text{Interpretation: } \Delta x = 1 \Rightarrow \Delta \hat{y} \approx 0.63 \]
The equality between the lm() slope and the
covariance-variance formula confirms the relationship discussed in
class:
\[ \hat{\beta}_1 = \frac{Cov(y,x)}{Var(x)} \]
The course data-structure notes were useful for distinguishing cross-sectional, time series, pooled cross-sectional, and panel data. The Week 2 lecture notes and beta coefficient handout were useful for connecting the fitted simple regression line to the covariance-variance formula for the slope coefficient.
\[ \hat{\beta}_1 = \frac{Cov(y,x)}{Var(x)} \]