Introduction

Our big question for the Perch dataset is: Can you weigh a perch with a ruler? Specifically, we want to know how far off a straight-line model is when predicting a perch’s weight from its length, and how much we should trust that line.

First, we load the required packages and the Perch dataset.

library(Stat2Data)
library(dplyr)
library(ggplot2)

data("Perch")
my_data <- Perch

Step 1: Scatterplot, Correlation, and Fitting the Line

We start by plotting Weight (the response variable, in grams) against Length (the explanatory variable, in cm), computing the correlation \(r\), and fitting a linear regression model.

ggplot(my_data, aes(x = Length, y = Weight)) +
  geom_point(alpha = 0.6) +
  labs(
    title = "Perch Weight vs. Length",
    x = "Length (cm)",
    y = "Weight (grams)"
  )

cor(my_data$Length, my_data$Weight, use = "complete.obs")
## [1] 0.9595061
model <- lm(Weight ~ Length, data = my_data)
coef(model)
## (Intercept)      Length 
##  -652.78714    35.00089

The correlation between length and weight is \(r = 0.95\). From the linear model, the intercept is \(-652.78\) and the slope is \(35.0\). Both \(r\) and the slope are positive, indicating a strong positive association between perch length and weight.

Step 2: Visualizing the Line and Calculating One Residual by Hand

Next, we add our fitted line to the scatterplot and inspect the first observation (Obs 104) to compute its residual by hand using \(\text{residual} = \text{actual } y - \text{predicted } y\).

ggplot(my_data, aes(x = Length, y = Weight)) +
  geom_point(alpha = 0.6) +
  geom_abline(intercept = -652.78, slope = 35.0, color = "steelblue") +
  labs(
    title = "Perch Weight vs. Length with Fitted Line",
    x = "Length (cm)",
    y = "Weight (grams)"
  )

my_data %>%
  select(Obs, Length, Weight) %>%
  head(1)
##   Obs Length Weight
## 1 104    8.8    5.9
5.9 - (35.0 * 8.8 + -652.78)
## [1] 350.68

For observation 104, the perch has an actual length of \(8.8\text{ cm}\) and an actual weight of \(5.9\text{ grams}\). Calculating the residual by hand gives \(350.68\). Because this residual is positive, the actual data point sits 350.68 grams above the fitted line.

Step 3: All Residuals and the Residual Plot

Now we calculate the predicted values and residuals for every fish in the dataset and examine a residual plot to check whether a straight line is appropriate.

my_data <- my_data %>%
  mutate(
    predicted = fitted(model),
    residual = residuals(model)
  )

my_data %>%
  select(Length, Weight, predicted, residual) %>%
  head()
##   Length Weight   predicted  residual
## 1    8.8    5.9 -344.779274 350.67927
## 2   14.7   32.0 -138.274002 170.27400
## 3   16.0   40.0  -92.772841 132.77284
## 4   17.2   51.5  -50.771769 102.27177
## 5   18.5   70.0   -5.270607  75.27061
## 6   19.2  100.0   19.230019  80.76998
ggplot(my_data, aes(x = Length, y = residual)) +
  geom_point(alpha = 0.6) +
  geom_hline(yintercept = 0, color = "steelblue") +
  labs(
    title = "Residual Plot: Perch Weight vs. Length",
    x = "Length (cm)",
    y = "Residual (grams)"
  )

The residual plot is curved rather than a boring, randomly scattered cloud of points. Specifically, the line predicts too high for perch around \(20\text{--}40\text{ cm}\) and predicts too low for perch around \(10\text{--}20\text{ cm}\) and \(40\text{--}50\text{ cm}\). Because the residuals follow a clear curved pattern rather than scattering randomly around zero, a straight line is not an appropriate model for these data.

Step 4: R-Squared and the Residual Standard Error

Finally, we inspect the model summary to evaluate how much variation in weight is explained by length and the typical size of our prediction errors.

summary(model)
## 
## Call:
## lm(formula = Weight ~ Length, data = my_data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -146.25  -57.86  -23.99   45.00  350.68 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -652.787     43.407  -15.04   <2e-16 ***
## Length        35.001      1.398   25.03   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 98.82 on 54 degrees of freedom
## Multiple R-squared:  0.9207, Adjusted R-squared:  0.9192 
## F-statistic: 626.5 on 1 and 54 DF,  p-value: < 2.2e-16

Overall, while length explains \(92.07\%\) of the variation in perch weight, we should not fully trust a straight-line model to weigh a perch with a ruler: typical predictions are off by about \(98.82\text{ grams}\), and the curved residual plot shows that a linear model systematically under-predicts for smaller and larger fish while over-predicting for mid-sized fish.