Introduction

In this analysis, we investigate the RailsTrails dataset from the Stat2Data package.

Big Question: Can you estimate a Northampton home’s value from its square footage? Additionally, how far off is our linear model’s prediction, and how much should we trust it?

Step 1: Data Exploration and Linear Model

We load the required R packages, inspect the dataset, plot home prices against square footage, and evaluate the linear correlation coefficient \(r\).

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

data("RailsTrails")
my_data <- RailsTrails

# Scatterplot of response vs. explanatory variable
ggplot(my_data, aes(x = SquareFeet, y = Price2014)) +
  geom_point(alpha = 0.7) +
  labs(
    title = "Home Value vs. Square Footage in Northampton",
    x = "Square Feet (thousands of sq ft)",
    y = "Price 2014 (thousands of dollars)"
  )

# Calculate linear correlation coefficient r
cor(my_data$SquareFeet, my_data$Price2014)
## [1] 0.8016692

The correlation coefficient between home square footage and 2014 price is 0.8016692, indicating a strong, positive linear relationship.

Next, we fit a linear regression model with Price2014 as our response variable and SquareFeet as our explanatory variable.

model <- lm(Price2014 ~ SquareFeet, data = my_data)
coef(model)
## (Intercept)  SquareFeet 
##    43.77116   159.16895

From the output: - Intercept (\(\hat{\beta}_0\)): 43.77116 - Slope (\(\hat{\beta}_1\)): 159.16895

The equation of our regression line is: \[\widehat{\text{Price2014}} = 43.77116 + 159.16895 \times \text{SquareFeet}\]

Step 2: One Residual by Hand

A residual measures how far an actual data point lies vertically from the fitted regression line: \[\text{Residual} = \text{Actual } y - \text{Predicted } \hat{y}\]

Below is the scatterplot displaying the fitted regression line using our calculated slope and intercept.

ggplot(my_data, aes(x = SquareFeet, y = Price2014)) +
  geom_point(alpha = 0.7) +
  geom_abline(intercept = 43.77116, slope = 159.16895, color = "steelblue") +
  labs(
    title = "Home Value vs. Square Footage with Fitted Line",
    x = "Square Feet (thousands of sq ft)",
    y = "Price 2014 (thousands of dollars)"
  )

# Inspect the first house in the dataset
my_data %>%
  select(HouseNum, SquareFeet, Price2014) %>%
  head(1)
##   HouseNum SquareFeet Price2014
## 1        1      0.966   210.729

For the first house in the dataset (HouseNum row 1): - Actual \(x\) (SquareFeet): 0.966 - Actual \(y\) (Price2014): 210.729

Calculating the residual by hand: \[\text{Predicted } \hat{y} = 43.77116 + 159.16895 \times (0.966) = 197.52836\] \[\text{Residual} = 210.729 - 197.52836 = 13.20064\]

Interpretation: The specific point for this house lies above the regression line by approximately 13.201 thousand dollars (or $13,201).

Step 3: Residual Analysis and Residual Plot

We add fitted values and residuals for every observation in my_data using mutate().

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

my_data %>%
  select(HouseNum, SquareFeet, Price2014, predicted, residual) %>%
  head()
##   HouseNum SquareFeet Price2014 predicted    residual
## 1        1      0.966   210.729  197.5284   13.200639
## 2        2      0.960   204.171  196.5733    7.597652
## 3        3      1.725   338.662  318.3376   20.324408
## 4        4      1.727   276.250  318.6559  -42.405930
## 5        5      1.576   169.173  294.6214 -125.448419
## 6        6      1.320   211.487  253.8742  -42.387169

Next, we evaluate the residual plot to assess whether a linear model is appropriate.

ggplot(my_data, aes(x = SquareFeet, y = residual)) +
  geom_point(alpha = 0.6) +
  geom_hline(yintercept = 0, color = "steelblue") +
  labs(
    title = "Residual Plot: Residuals vs. Square Footage",
    x = "Square Feet (thousands of sq ft)",
    y = "Residual (thousands of dollars)"
  )

Interpretation: The residual plot appears “boring” — the points form a random, patternless cloud centered around zero with balanced vertical spread. This confirms that fitting a straight line to this relationship is appropriate.

Step 4: Assessing Model Fit (\(R^2\) and RSE)

Finally, we run summary(model) to determine how well square footage explains variation in home values and measure the typical size of our prediction errors.

summary(model)
## 
## Call:
## lm(formula = Price2014 ~ SquareFeet, data = my_data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -172.13  -38.20   -2.05   28.33  330.20 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    43.77      19.53   2.241   0.0272 *  
## SquareFeet    159.17      11.75  13.544   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 66.61 on 102 degrees of freedom
## Multiple R-squared:  0.6427, Adjusted R-squared:  0.6392 
## F-statistic: 183.5 on 1 and 102 DF,  p-value: < 2.2e-16

From the summary output: - Multiple R-squared (\(R^2\)): 0.6427 - Residual Standard Error (RSE): 66.62

Interpretations: 1. \(R^2\) (0.6427): Approximately 64.27% of the variation in home prices (Price2014) is explained by the linear relationship with square footage (SquareFeet). 2. Residual Standard Error (66.62): Actual home prices in Northampton typically deviate from the model’s predictions by about 66.62 thousand dollars (or $66,620).

Conclusion

Square footage is a strong predictor of home value in Northampton. Our model accounts for nearly two-thirds of the variation in price, though typical predictions carry an average margin of error of around $66,620.