Suppose you want to estimate a product’s shipping cost from its weight or volume. A regression line may show a relationship, yet leave actual freight values widely scattered around it. R², the coefficient of determination, helps quantify how much of the variation in freight value the chosen inputs explain. section 3.4.2
R² measures the proportion of variation in a dependent variable explained by a regression model’s independent variables. Higher R² generally indicates better predictive performance, but it is not a measure of how far individual predictions miss. Read it alongside error metrics such as mean absolute error (MAE) and root mean squared error (RMSE), and inspect the scatterplot. section 3.4.2
Weight, volume, and freight value
A weight-only model has R² = 0.37; a volume-only model has R² = 0.34. Together, weight and volume produce R² = 0.399. The combined model explains more of the observed variation, but freight values remain widely spread: a package weighing 20 kg could correspond to a broad range of costs. Check the accompanying MAE and RMSE before relying on any of these models for a quote. section 3.4.2 section 4.6
Listing 3.4 Predicting product weight or volume influence on freight value
from sklearn.metrics import mean_absolute_error, mean_squared_error,
r2_score
# Split the data into features (X) and target (y)
X_weight = analysis_df["product_weight_g"].values.reshape(-1, 1)
X_weight = sm.add_constant(X_weight) # Add a constant for the intercept
X_volume = analysis_df["product_volume"].values.reshape(-1, 1)
X_volume = sm.add_constant(X_volume) # Add a constant for the intercept
y = analysis_df["freight_value"].values
# Predict the target variable using the models
y_pred_weight = model_weight.predict(X_weight)
y_pred_volume = model_volume.predict(X_volume)
# Calculate the evaluation metrics for both models
mae_weight = mean_absolute_error(y, y_pred_weight)
mse_weight = mean_squared_error(y, y_pred_weight)
rmse_weight = np.sqrt(mse_weight)
r2_weight = r2_score(y, y_pred_weight)
mae_volume = mean_absolute_error(y, y_pred_volume)
mse_volume = mean_squared_error(y, y_pred_volume)
rmse_volume = np.sqrt(mse_volume)
r2_volume = r2_score(y, y_pred_volume)
# Print the evaluation metrics
print(f"Product Weight Model: MAE={mae_weight:.2f}, MSE={mse_weight:.2f},
RMSE={rmse_weight:.2f}, R2={r2_weight:.2f}")
print(f"Product Volume Model: MAE={mae_volume:.2f}, MSE={mse_volume:.2f},
RMSE={rmse_volume:.2f}, R2={r2_volume:.2f}")
The Python workflow predicts freight value with separate weight and volume models, then uses scikit-learn’s r2_score alongside error metrics to compare their outputs. section 3.4.2
Do not report only the largest R². A near-zero result can still matter when testing a proposed business relationship, while a surprising result deserves investigation. In a retention-campaign example, a reported negative R² appeared alongside evidence that messaged customers were less likely to repurchase. Examine the underlying outcome rather than treating a single metric as the whole explanation. section 4.6






