Linear Regression Analysis in Python

Run simple and multiple linear regression, interpret coefficients, check assumptions, and evaluate model fit using statsmodels and scikit-learn.

This page shows an AI data analysis example. A workflow is a list of prompts (instructions) used to complete one analysis task step by step. We send the same prompt list to multiple AI models, then compare their notebook outputs and scores.

What this AI workflow does

This AI Data Analyst workflow loads the Boston Housing dataset from a URL and fits a simple linear regression of RM (rooms) versus MEDV (price). It then fits a multiple linear regression using all features and generates a statsmodels OLS summary for coefficient and p-value interpretation. The workflow checks key regression assumptions with residual and Q-Q plots, evaluates homoscedasticity, and compares model fit between the simple and multiple models using R-squared.

Who this example is for

This is for analysts and students who want a guided, code-generating notebook to run and interpret linear regression in Python. It helps users validate assumptions and compare simple versus multiple regression using standard statistical outputs and diagnostics.

Expected analysis outcomes

These are the results the AI workflow is expected to generate.

  • Dataset loaded from the provided CSV URL
  • Simple regression scatter plot with fitted line and R-squared around 0.48
  • Multiple regression OLS summary table with coefficients and p-values
  • Residual and Q-Q diagnostic plots with a homoscedasticity check
  • R-squared comparison showing roughly 0.48 (simple) versus 0.74 (multiple)

Tools and libraries used

Main Python packages and tooling used to run this AI data analysis task.

  • pandas
  • numpy
  • statsmodels
  • scikit-learn
  • matplotlib
  • seaborn

Prompt sequence

This is the exact list of prompts used in this workflow. The same prompt sequence is sent to each model so outputs and scores can be compared fairly.

  1. 1load boston housing data from https://raw.githubusercontent.com/pplonski/datasets-for-start/refs/heads/master/housing/data.csv and run simple linear regression: rm (rooms) vs medv (price)
  2. 2run multiple linear regression with all features and show the statsmodels summary
  3. 3check regression assumptions: residual plot, Q-Q plot, homoscedasticity
  4. 4compare R-squared of simple vs multiple regression

Model Comparison

We compared several LLM models on the same analysis task. The table below shows their scores side by side. You can also open each model run to check the full conversation and notebook results.

Model SourceScoreTaskExecutionOutputReasoningReliabilityRun
gemma4:31b10/102/22/23/32/21/1Open gemma4:31b conversation
glm-5.110/102/22/23/32/21/1Open glm-5.1 conversation
gpt-5.410/102/22/23/32/21/1Open gpt-5.4 conversation
gpt-oss:120b10/102/22/23/32/21/1Open gpt-oss:120b conversation
qwen3-coder-next10/102/22/23/32/21/1Open qwen3-coder-next conversation
qwen3.5:397b10/102/22/23/32/21/1Open qwen3.5:397b conversation
How scoring works

Each run is graded on five dimensions:

  • Task Completion (0-2): how fully the workflow answered the requested analysis task and completed required steps.
  • Execution Correctness (0-2): whether generated code is correct, consistent, and likely runnable without major fixes.
  • Output Quality (0-3): how well tables, charts, and results match the expected analytical outcomes.
  • Reasoning Quality (0-2): clarity and correctness of interpretation, explanation, and conclusions.
  • Reliability (0-1): robustness of the run, including low hallucination risk and stable behavior.

The final score is the sum of these dimensions, so total score = 0-10. Higher values indicate more complete, correct, and reliable notebook results for this workflow.

AI Analysis with gemma4:31b

This run uses AI with a step-by-step list of prompts to perform the analysis task Linear Regression Analysis in Python. Below, you can review the full conversation generated with gemma4:31b. After the conversation, we show detailed score cards for this run.

load boston housing data from https://raw.githubusercontent.com/pplonski/datasets-for-start/refs/heads/master/housing/data.csv and run simple linear regression: rm (rooms) vs medv (price)
Thinking

The user wants to load the Boston Housing dataset from a specific URL and perform a simple linear regression between rm (average number of rooms per dwelling) and medv (median value of owner-occupied homes).

Following the "AI Data Analyst" instructions:

  1. Iterative approach: I cannot do the load and the regression in one go.
  2. Rule: "When a dataset is not yet loaded in current notebook context, first load and inspect only: show shape, columns, and head()."
  3. Rule: "Do not combine first-load data inspection with plotting/modeling in the same response."

Step 1: Load the data and inspect it.

I'll start by loading the dataset and inspecting its structure to make sure the columns rm and medv are present.

Load and inspect data
import pandas as pd

url = "https://raw.githubusercontent.com/pplonski/datasets-for-start/refs/heads/master/housing/data.csv"
df = pd.read_csv(url)

# Inspect the dataset
print(f"Shape: {df.shape}")
display(df.head())
display(df.columns)
Shape: (506, 14)
CRIM ZN INDUS CHAS NOX RM AGE DIS RAD TAX PTRATIO B LSTAT MEDV
0 0.00632 18.0 2.31 0 0.538 6.575 65.2 4.0900 1 296 15.3 396.90 4.98 24.0
1 0.02731 0.0 7.07 0 0.469 6.421 78.9 4.9671 2 242 17.8 396.90 9.14 21.6
2 0.02729 0.0 7.07 0 0.469 7.185 61.1 4.9671 2 242 17.8 392.83 4.03 34.7
3 0.03237 0.0 2.18 0 0.458 6.998 45.8 6.0622 3 222 18.7 394.63 2.94 33.4
4 0.06905 0.0 2.18 0 0.458 7.147 54.2 6.0622 3 222 18.7 396.90 5.33 36.2
Index(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX',
       'PTRATIO', 'B', 'LSTAT', 'MEDV'],
      dtype='str')
Thinking

The dataset is loaded. It has 506 rows and 14 columns. The target column MEDV (median value) and the predictor RM (average number of rooms) are present. The user wants a simple linear regression of RM vs MEDV. I have only loaded and inspected the data. I haven't performed the regression yet.

Path B is required. I need to perform the linear regression.

Plan:

  1. Import LinearRegression from sklearn.linear_model.
  2. Reshape RM to be a 2D array as required by scikit-learn.
  3. Fit the model and extract the coefficients (slope and intercept).
  4. Display the results.

The dataset is loaded with 506 entries, and both the predictor RM (average number of rooms) and the target MEDV (median house value) are available. I will now perform the simple linear regression.

Fit linear regression model
from sklearn.linear_model import LinearRegression

# Prepare the data
X = df[['RM']]
y = df['MEDV']

# Initialize and fit the model
model = LinearRegression()
model.fit(X, y)

# Extract results
slope = model.coef_[0]
intercept = model.intercept_

# Display results
print(f"Slope: {slope:.4f}")
print(f"Intercept: {intercept:.4f}")
print(f"Equation: MEDV = {slope:.4f} * RM + {intercept:.4f}")
Slope: 9.1021
Intercept: -34.6706
Equation: MEDV = 9.1021 * RM + -34.6706
Thinking

The user wants to load the Boston housing data and run a simple linear regression of RM (rooms) vs MEDV (price).

Looking at the notebook state:

  1. Data was loaded from the specified URL.
  2. RM and MEDV columns were identified.
  3. A LinearRegression model was fitted using X = df[['RM']] and y = df['MEDV'].
  4. The output shows:
    • Slope: 9.1021
    • Intercept: -34.6706
    • Equation: MEDV = 9.1021 * RM + -34.6706

The original goal was to "load... and run simple linear regression: rm (rooms) vs medv (price)". The model has been run and the coefficients (slope and intercept) are provided. This satisfies the core request.

Wait, the prompt asks me to act as a data analyst and extract concrete insights.

  • Slope 9.1021 means that for every additional room, the median house value increases by approximately 9.1021 units (typically thousands of USD in the Boston dataset, though the dataset just says MEDV). I should just use the numeric value or USD notation if I treat it as currency, but the dataset labels it as MEDV. Actually, the rule says "never use $ for money/currency values... always write amounts using USD". 9.1021 units of 1000 USD = 9102.10 USD. However, the prompt says "amounts using USD", so I should be careful. Let's just state the coefficient effect.

Is there anything missing? The goal was to "run" the regression. It has been run and the parameters are printed. This is sufficient for a "simple linear regression" request unless a plot or evaluation metrics were explicitly requested. The prompt doesn't ask for a plot, just to run it.

Therefore, Path A is appropriate.

Insights:

  • The positive slope of 9.1021 indicates a positive correlation between the number of rooms (RM) and the median value (MEDV).
  • Specifically, each additional room is associated with an average increase of 9.1021 units in the median house value.
  • The linear model is described by the equation: $\text{MEDV} = 9.1021 \times \text{RM} - 34.6706$.

Final check on currency rule: "never use $ for money/currency values... Always write amounts using USD". If I mention the value, I'll use USD. In the Boston dataset, MEDV is usually in 1000s of USD. If the value is 24.0, that's 24,000 USD. If the slope is 9.1, that's 9,100 USD. I will stick to the units provided in the output to be safe or just describe the coefficients.

The result is: Slope: 9.1021 Intercept: -34.6706

The model suggests that as the number of rooms increases, the median value of the home increases by approximately 9.1021 units per room.

<!--final answer-->

The simple linear regression analysis shows a positive relationship between the number of rooms (RM) and the median house value (MEDV). With a slope of 9.1021, the model indicates that for every additional room, the median house value increases by approximately 9.1021 units.

The resulting regression equation is: \text{MEDV} = 9.1021 × \text{RM} - 34.6706

run multiple linear regression with all features and show the statsmodels summary
Thinking

The user wants to perform a multiple linear regression using all available features from the dataset and display the summary using the statsmodels library.

- `df`: DataFrame with 506 rows and 14 columns.
- Features: `CRIM`, `ZN`, `INDUS`, `CHAS`, `NOX`, `RM`, `AGE`, `DIS`, `RAD`, `TAX`, `PTRATIO`, `B`, `LSTAT`.
- Target: `MEDV`.

- Use `statsmodels.api` for the regression model.
- Define `X` (all features except `MEDV`) and `y` (`MEDV`).
- Add a constant term to the features (since `statsmodels` doesn't add an intercept by default).
- Fit the OLS model.
- Display the summary.

- I need to identify the features. All columns except `MEDV`.
- I need to use `sm.OLS`.
- I need to use `sm.add_constant(X)`.

- One code block.
- Focus on `statsmodels`.
- No identifier/leakage columns? All columns in this dataset seem to be features. No `Id` column present based on `df.columns`.

- Propose the step.
- Provide code.
- Wait for results.

To perform multiple linear regression and get a detailed statistical summary, I will use the statsmodels library, as it provides a comprehensive summary table including p-values and R-squared.

Fit OLS regression model
import statsmodels.api as sm

# Define features (X) and target (y)
X_all = df.drop(columns=['MEDV'])
y_all = df['MEDV']

# Add a constant term to the predictors for the intercept
X_all_with_const = sm.add_constant(X_all)

# Fit the Ordinary Least Squares (OLS) model
mlr_model = sm.OLS(y_all, X_all_with_const).fit()

# Display the summary
mlr_model.summary()
OLS Regression Results
Dep. Variable: MEDV R-squared: 0.741
Model: OLS Adj. R-squared: 0.734
Method: Least Squares F-statistic: 108.1
Date: Sat, 11 Apr 2026 Prob (F-statistic): 6.72e-135
Time: 20:29:01 Log-Likelihood: -1498.8
No. Observations: 506 AIC: 3026.
Df Residuals: 492 BIC: 3085.
Df Model: 13
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
const 36.4595 5.103 7.144 0.000 26.432 46.487
CRIM -0.1080 0.033 -3.287 0.001 -0.173 -0.043
ZN 0.0464 0.014 3.382 0.001 0.019 0.073
INDUS 0.0206 0.061 0.334 0.738 -0.100 0.141
CHAS 2.6867 0.862 3.118 0.002 0.994 4.380
NOX -17.7666 3.820 -4.651 0.000 -25.272 -10.262
RM 3.8099 0.418 9.116 0.000 2.989 4.631
AGE 0.0007 0.013 0.052 0.958 -0.025 0.027
DIS -1.4756 0.199 -7.398 0.000 -1.867 -1.084
RAD 0.3060 0.066 4.613 0.000 0.176 0.436
TAX -0.0123 0.004 -3.280 0.001 -0.020 -0.005
PTRATIO -0.9527 0.131 -7.283 0.000 -1.210 -0.696
B 0.0093 0.003 3.467 0.001 0.004 0.015
LSTAT -0.5248 0.051 -10.347 0.000 -0.624 -0.425
Omnibus: 178.041 Durbin-Watson: 1.078
Prob(Omnibus): 0.000 Jarque-Bera (JB): 783.126
Skew: 1.521 Prob(JB): 8.84e-171
Kurtosis: 8.281 Cond. No. 1.51e+04


Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.51e+04. This might indicate that there are
strong multicollinearity or other numerical problems.
Thinking

The user wants to run a multiple linear regression with all features and see the statsmodels summary. Looking at the provided notebook state:

  • cell-3 executed the statsmodels OLS regression using all features (X_all).
  • output-3 contains the OLS Regression Results summary.
  • The summary shows an R-squared of 0.741 and an Adjusted R-squared of 0.734.
  • The goal was specifically to "run multiple linear regression with all features and show the statsmodels summary".
  • The summary is visible in the output.

The original goal has been met. I can now provide a final answer based on the observed outputs.

Insights from the summary:

  • R-squared: 0.741 (The model explains approximately 74.1% of the variance in the median house value MEDV).
  • Adj. R-squared: 0.734 (Correcting for the number of predictors, the model explains 73.4% of the variance).
  • F-statistic: 108.1 with a very low p-value (6.72e-135), indicating the model is statistically significant.

Decision: Path A.

The multiple linear regression model using all available features explains approximately 74.1% of the variance in the median house value (R-squared: 0.741), with an adjusted R-squared of 0.734. The F-statistic of 108.1 and the extremely low p-value (\6.72 × 10^{-135}) indicate that the overall model is statistically significant.

check regression assumptions: residual plot, Q-Q plot, homoscedasticity
Thinking

The user wants to check the regression assumptions for the previously fitted mlr_model (Multiple Linear Regression). Specifically, they want:

  1. Residual plot (to check for linearity and patterns).
  2. Q-Q plot (to check for normality of residuals).
  3. Homoscedasticity check (usually done via residuals vs. fitted values plot or similar).

Notebook state:

  • df is loaded.
  • mlr_model is the fitted statsmodels OLS model.
  • Target variable is MEDV.
  • Features are all other columns.

Plan:

  • I need to get the residuals and the fitted values from mlr_model.
  • I will use seaborn and matplotlib as per the visualization policy.
  • Since the user asked for three different things, I should follow the "one chart per step" rule OR provide a combined figure if it's standard for "checking assumptions". However, the rules say "Default to one chart OR one table per step" and "Do not provide a full end-to-end pipeline at once".
  • But for "checking assumptions", these three are usually seen together. Let's start with the Residual Plot first to see if there's a non-linear pattern.
  • Wait, the user explicitly asked for all three. I'll start with the Residual Plot (Residuals vs Fitted) which is the primary diagnostic for linearity and homoscedasticity. Then in the next turn, I'll do the Q-Q plot.

Step 1: Residual Plot (Fitted values vs Residuals). This helps check for linearity and homoscedasticity (constant variance).

Wait, the prompt asks for "residual plot, Q-Q plot, homoscedasticity". If I only do one, I'm ignoring part of the request. If I do all, I might violate the "one chart per step" rule. Usually, in a data science workflow, we can put these in subplots. But the rule says "one chart per step". I'll start with the Residual plot as it's the most fundamental.

Actually, looking at the "Visualization defaults" section: "Default to one chart OR one table per step." I will propose to do these one by one.

First step: Residual plot.

Code:

  • Calculate fitted values: mlr_model.predict(X_all_with_const)
  • Calculate residuals: mlr_model.resid
  • Plot fitted vs resid.

Wait, let me double check if I can do a 2x2 or 1x3 grid. The rules are quite strict: "Default to one chart OR one table per step." I'll stick to one. I'll start with the Residual plot.

Wait, a better way to check homoscedasticity and linearity is the same plot (Residuals vs Fitted). So I'll do that first.

Wait, the user prompt is "check regression assumptions: residual plot, Q-Q plot, homoscedasticity". I will start with the Residual Plot (Fitted vs Residuals).

To check the regression assumptions, we should start with a Residual Plot (fitted values vs. residuals). This plot helps us verify linearity (if the residuals are randomly scattered around zero) and homoscedasticity (if the spread of residuals is constant across all fitted values).

Plot residuals
import matplotlib.pyplot as plt
import seaborn as sns

# Calculate fitted values and residuals
fitted_values = mlr_model.predict(X_all_with_const)
residuals = mlr_model.resid

# Create the Residual Plot
plt.figure(figsize=(10, 6))
sns.scatterplot(x=fitted_values, y=residuals)
plt.axhline(y=0, color='red', linestyle='--')
plt.title('Residual Plot: Fitted Values vs Residuals')
plt.xlabel('Fitted Values')
plt.ylabel('Residuals')
plt.show()
Thinking

The user wants to check regression assumptions: residual plot, Q-Q plot, and homoscedasticity. Looking at the notebook state:

  • [cell-4] and [output-4] show a Residual Plot (Fitted Values vs Residuals).
  • We are missing the Q-Q plot (to check normality of residuals).
  • We have the residual plot, which is the first step for homoscedasticity, but we haven't specifically addressed the normality check (Q-Q plot).

The original goal is "check regression assumptions: residual plot, Q-Q plot, homoscedasticity". Current state: Residual plot done. Q-Q plot missing.

Analysis of the residual plot:

  • The residuals are plotted against fitted values. This allows us to check for non-linearity (patterns) and heteroscedasticity (changing variance). While the image is not explicitly described in text output, the code was executed.

Plan:

  1. Provide insights on the residual plot (assuming the user can see it, but since I am an AI analyst, I should mention what it evaluates).
  2. Provide the code for the Q-Q plot to complete the normality check.

Wait, the sufficiency heuristic says "If the latest output is chart-only... choose Path B". Output-4 is a figure. I need to provide the Q-Q plot.

Actually, the goal mentions three things: residual plot (done), Q-Q plot (missing), and homoscedasticity (partially checked via residual plot, but often a formal check or a specific plot is used).

I will provide the Q-Q plot now.

Insights: The residual plot allows us to observe if the residuals are randomly distributed around zero. If a "funnel" shape appears, it indicates heteroscedasticity. If a curve appears, it indicates non-linearity.

Next step: Q-Q plot.

The residual plot provides an initial look at linearity and homoscedasticity; a random scatter around the zero line suggests these assumptions hold, while any funnel shape would indicate heteroscedasticity. To complete the assumption checks, we now need a Q-Q plot to verify if the residuals are normally distributed.

Plot Q-Q plot
import scipy.stats as stats

# Create the Q-Q plot
plt.figure(figsize=(10, 6))
stats.probplot(residuals, dist="norm", plot=plt)
plt.title('Normal Q-Q Plot')
plt.xlabel('Theoretical Quantiles')
plt.ylabel('Sample Quantiles')
plt.grid(True)
plt.show()
Thinking
  • Goal: Check regression assumptions: residual plot, Q-Q plot, homoscedasticity.
    • State:

      • mlr_model (OLS) is fitted.
      • Residual Plot (Fitted vs Residuals) has been generated.
      • Q-Q Plot (Normal distribution check) has been generated.
    • Analysis of Goal vs state:

      • Residual plot: Done.
      • Q-Q plot: Done.
      • Homoscedasticity: The residual plot is the primary visual tool for this, but for a formal check, a statistical test like the Breusch-Pagan test is standard and provides a definitive answer rather than just visual intuition.
    • Residual Plot: Visually checks for linearity and homoscedasticity (constant variance).

    • Q-Q Plot: Visually checks if residuals are normally distributed.

    • Homoscedasticity check: The user explicitly asked for "homoscedasticity". While the residual plot addresses this visually, a formal test (like Breusch-Pagan) is the professional way to "check" it beyond just "looking".

    • The goal was to "check" these things. We have visual plots, but we lack a statistical confirmation for homoscedasticity.

    • Path B is appropriate to provide the statistical test for homoscedasticity to complete the set of "checks".

    • Insights: The residual plot helps identify patterns (linearity/variance), and the Q-Q plot evaluates normality.

    • Action: Perform a Breusch-Pagan test for homoscedasticity.

The residual plot allows us to visually inspect for linearity and constant variance, while the Q-Q plot evaluates whether the residuals follow a normal distribution. To move beyond visual intuition and formally check for homoscedasticity, we can perform the Breusch-Pagan test.

Perform Breusch-Pagan test
from statsmodels.stats.diagnostic import het_breuschpagan

# Perform the Breusch-Pagan test
# The test returns the Lagrange Multiplier statistic, the p-value, an F-statistic, and its p-value
bp_test = het_breuschpagan(residuals, X_all_with_const)

print(f"Breusch-Pagan Test: LM Statistic = {bp_test[0]:.4f}, p-value = {bp_test[1]:.4e}")
Breusch-Pagan Test: LM Statistic = 65.1218, p-value = 6.2654e-09
Thinking
  • Goal: Check regression assumptions (residual plot, Q-Q plot, homoscedasticity).
    • State:

      • Cell 4: Residual plot generated (visual check for linearity and homoscedasticity).
      • Cell 5: Q-Q plot generated (visual check for normality of residuals).
      • Cell 6: Breusch-Pagan test executed. Output: LM Statistic = 65.1218, p-value = 6.2654e-09.
    • Residual Plot: Used to check for non-linearity and heteroscedasticity. (Done)

    • Q-Q Plot: Used to check for normality. (Done)

    • Homoscedasticity: Breusch-Pagan test provided a p-value of $6.2654 \times 10^{-9}$. This is significantly below 0.05, meaning we reject the null hypothesis of homoscedasticity. The data exhibits heteroscedasticity. (Done)

    • The user goal was to "check" these assumptions.

    • Residual plot -> Done.

    • Q-Q plot -> Done.

    • Homoscedasticity (BP test) -> Done.

    • All components of the request have been addressed with both visual and statistical evidence.

    • Path A is appropriate because the outputs are sufficient to answer the goal.

    • Insights:

      • Residual plot: Visual check for patterns.
      • Q-Q plot: Visual check for normality.
      • Breusch-Pagan test: The extremely low p-value ($6.2654 \times 10^{-9}$) indicates a statistically significant presence of heteroscedasticity, meaning the variance of the residuals is not constant across the range of predictors.
    • Ensure no $ for currency (not applicable here, but keep in mind).

    • Include <!--final answer-->.

    • No code block.

    • No "goal achieved" phrases.

Based on the executed analysis, here is the evaluation of the regression assumptions:

  1. Linearity and Homoscedasticity (Residual Plot): The residual plot allows for a visual check of the error distribution. A random scatter would suggest linearity and constant variance; any distinct patterns (like a funnel shape) indicate a violation.
  2. Normality of Residuals (Q-Q Plot): The Q-Q plot compares the sample quantiles of the residuals against the theoretical quantiles of a normal distribution. Deviations from the straight line, particularly at the ends, suggest that the residuals are not perfectly normally distributed.
  3. Homoscedasticity (Breusch-Pagan Test): The Breusch-Pagan test provides a formal statistical check. The resulting p-value of \6.2654 × 10^{-9} is well below the standard significance level of 0.05. We reject the null hypothesis of homoscedasticity, confirming that the model suffers from heteroscedasticity (non-constant variance of the residuals).
compare R-squared of simple vs multiple regression
Thinking

The user wants to compare the $R^2$ (R-squared) values of a simple linear regression (SLR) and a multiple linear regression (MLR).

*   `cell-2`: Simple Linear Regression (SLR) using `LinearRegression` from `sklearn` with feature `RM` and target `MEDV`.
*   `cell-3`: Multiple Linear Regression (MLR) using `sm.OLS` from `statsmodels` with all features.
*   `output-3`: The summary shows `R-squared: 0.741` for the MLR.

*   SLR was fit using `sklearn.linear_model.LinearRegression`.
*   The $R^2$ for SLR is not yet computed/printed in the provided notebook state. Only slope and intercept were printed.

*   Need to calculate $R^2$ for the SLR model.
*   Need to retrieve $R^2$ for the MLR model.
*   Compare them.

*   SLR model was `model`.
*   `model.score(X, y)` provides the $R^2$ for `sklearn` models.
*   MLR model was `mlr_model`.
*   `mlr_model.rsquared` provides the $R^2$ for `statsmodels` models.

To compare the R^2 values, we need to calculate the coefficient of determination for the simple linear regression (which used only the RM feature) and retrieve the value from the multiple linear regression summary.

Compare R-squared values
# Calculate R-squared for the simple linear regression model
r2_simple = model.score(X, y)

# Get R-squared for the multiple linear regression model
r2_multiple = mlr_model.rsquared

print(f"Simple Linear Regression R-squared: {r2_simple:.4f}")
print(f"Multiple Linear Regression R-squared: {r2_multiple:.4f}")
print(f"Difference: {r2_multiple - r2_simple:.4f}")
Simple Linear Regression R-squared: 0.4835
Multiple Linear Regression R-squared: 0.7406
Difference: 0.2571
Thinking

The user wants to compare the $R^2$ of simple vs multiple regression.

Looking at the notebook state:

  • cell-2 performed Simple Linear Regression (model).
  • cell-3 performed Multiple Linear Regression (mlr_model).
  • cell-7 explicitly calculated and printed the $R^2$ for both:
    • Simple Linear Regression $R^2$: 0.4835
    • Multiple Linear Regression $R^2$: 0.7406
    • Difference: 0.2571

The original goal is "compare R-squared of simple vs multiple regression". The output of cell-7 provides the exact values and the difference. This is sufficient to answer the goal.

Conclusion: Path A.

The Multiple Linear Regression model performs significantly better than the Simple Linear Regression model. While the simple model (using only RM) explains approximately 48.35% of the variance in housing prices, the multiple regression model explains approximately 74.06%. This represents an increase of 0.2571 in R^2, indicating that including additional features provides a much better fit for the data.

Score cards for gemma4:31b for Linear Regression Analysis in Python

Total score: 10/10

  • Task Completion: 2/2

    Excellent

    All major requested steps were completed: simple regression, multiple regression with statsmodels summary, assumption checks, and R-squared comparison.

  • Execution Correctness: 2/2

    Excellent

    The code shown is coherent and likely runnable, and the outputs are consistent with the intended analyses.

  • Output Quality: 3/3

    Excellent

    Outputs match the expected outcomes semantically: regression line, full OLS summary, residual and Q-Q plots, Breusch-Pagan test, and R² values of about 0.48 and 0.74.

  • Reasoning Quality: 2/2

    Excellent

    The workflow correctly interprets the regression results and connects the diagnostics to the assumptions being checked.

  • Reliability: 1/1

    Excellent

    The workflow is consistent and not obviously hallucinated, with outputs supporting the stated conclusions.

Try MLJAR Studio

Run the same type of AI-powered data analysis on your own datasets with conversational notebooks in MLJAR Studio.

Explore More AI Analysis Examples

Discover additional workflows across categories. Each example includes prompts, conversation outputs, and model-level scoring so you can compare approaches and results.