Regression
Determine which operational factors drive store sales with multiple linear regression. Instead of static ANOVA tables that require manual recalculation, this template fits an ordinary least squares model directly from workbook data, evaluates statistical significance, and translates mathematical coefficients into plain-English business takeaways.
Result preview
Across 50 retail locations, the model explains 86.9% of store sales variance (\(R^2 = 0.869\), Adjusted \(R^2 = 0.854\)). Marketing spend is the strongest positive driver, adding approximately $3.4k in monthly sales for each extra $1k spent. Discounting represents the primary drag, reducing monthly sales by about $1.7k for each 1% increase in discount rate. Foot traffic provides strong positive uplift, staff hours provides modest positive lift, and store age shows no statistically significant relationship with sales.
What this template does
- Ingests monthly operational figures for 50 store locations: sales, marketing, staffing, foot traffic, discounts, and store age.
- Reads a user-configured significance threshold from worksheet settings (defaulting to 5%).
- Runs multiple linear regression via
statsmodelsto estimate unit effects, standard errors, and p-values. - Translates regression coefficients into clear operational statements (for example, “Each extra $1k of marketing adds about $3.4k of monthly sales”).
- Visualizes factor effect sizes with 95% confidence intervals and plots actual versus model-predicted store sales in the notebook.
- Publishes model fit summary statistics and the complete drivers table back to Excel via
BF.OUTPUT.
Why Python
Excel’s built-in Analysis ToolPak regression requires manual setup, outputs static arrays that break when data changes, and produces dense statistical tables without plain-language takeaways. Python in Excel runs automatically whenever store inputs or assumptions change, handles clean data coercion, and turns regression statistics into actionable operational insights beside the grid.
Edit store sales figures, adjust marketing spend, or modify the significance level. The driver takeaways and fit summary update immediately.
Operating workflow
Author: A data analyst or technical maintainer defines the target column, predictor mapping, unit wording, and published workbook anchors in notebook.py and workbook.py.
Workbook user: A retail operations analyst or regional manager pastes monthly store figures into the input table, adjusts significance thresholds, and reviews driver rankings and takeaways without editing code.
The template can also open in App mode to highlight inputs and published outputs. App mode is a presentation preference rather than a security or permissions boundary.
Download the Excel template
Inputs and assumptions
| Input | Location | Default | Description |
|---|---|---|---|
| Store figures | Stores!A16:G66 |
50 store rows | Store name, Monthly Sales (\(k), Marketing (\)k), Staff Hours, Foot Traffic (k), Discount (%), and Store Age (years) |
| Significance level | Stores!B6 |
5.0% | P-value cutoff for classifying a factor as statistically significant |
The model assumes linear additive relationships between predictors and store sales. Standard errors and p-values assume homoscedastic, normally distributed residuals.
Notebook implementation
The notebook reads the store table and significance setting via bf.inputs(...), fits an ordinary least squares regression, and publishes the fit summary and drivers table:
inputs = bf.inputs(
stores=bf.ref("Stores!A16:G66", headers=True),
significance="Stores!B6",
)
df = inputs["stores"].copy()
# ...clean numeric columns and parse significance level...
clean_df = df.dropna(subset=[TARGET_COLUMN] + list(PREDICTORS))
y = clean_df[TARGET_COLUMN]
X_cols = list(PREDICTORS.keys())
X = sm.add_constant(clean_df[X_cols])
model = sm.OLS(y, X).fit()
# ...build plain-English takeaways and summary table...
publication = bf.publish(
outputs={"summary": summary_rows, "drivers": driver_rows}
)How the calculation/model works
- Input validation & coercion: Store figures are cleaned of currency symbols and commas. A column with a
scalein the rules is multiplied by it: Discount is stored as a fraction (0.10for 10%) and scaled by 100, so its coefficient reflects a one-point change. The significance level is read as a decimal number (falling back to 0.05 if blank or invalid). - OLS estimation: The model estimates coefficients \(\beta_j\) that minimize squared prediction residuals.
- Significance testing: Each factor’s two-tailed p-value is compared against the chosen significance level \(\alpha\). Factors with \(p < \alpha\) are marked significant.
- Standardized comparison: Standardized coefficients (\(\beta_j \times s_{X_j} / s_Y\)) are computed to compare relative driver importance across differing measurement scales.
- Takeaway generation: Plain-English sentences are constructed stating the directional unit impact for significant factors or stating that no statistically significant effect was detected.
Architecture
- Predictor configuration and scaling: Predictors are declared in
PREDICTORSin the# --- Edit these rules ---cell ofnotebook.py, defining column names, custom phrasing for business takeaways, and optional scale multipliers (e.g. converting fractional percentages to integer percentage points). - Driver spill contract: The
driversoutput spill is anchored atStores!C5:G10(header plus 5 predictor rows). Adding or removing predictors requires updating the store table columns, thePREDICTORSdictionary, and thespillRefinworkbook.pyin lockstep. - Robust significance parsing:
Stores!B6accepts bare floats (0.05), percentage strings (“5%”), or integer percentages (5), normalising any value \(\ge 1.0\) down by 100 before applying the significance cutoff.
Validation / expected results
| Check | Expected outcome |
|---|---|
| Baseline \(R^2\) | 0.869 |
| Baseline Adjusted \(R^2\) | 0.854 |
| Total observations | 50 |
| Top positive driver | Marketing ($k) |
| Top drag | Discount (%) |
| Marketing effect per unit | +$3.4k per \(1k spent | | Staff hours significance (\)= 5%\() | Yes | | Store age significance (\)= 5%$) |
Tightening the significance level from 5% to 1% changes Staff Hours to not statistically significant while Marketing, Foot Traffic, and Discounting remain significant. Modifying store rows so sales increase with store age increases Store Age’s estimated unit effect and p-value significance.
Limitations
- Assumes linear relationships; does not capture diminishing returns to marketing or saturation points without non-linear terms.
- Does not test for multi-collinearity (e.g., foot traffic and staffing moving together) or outlier leverage points.
- Observational regression shows statistical correlation rather than controlled causal proof.
When to use this approach
Use this template to identify key business drivers across stores, territories, or marketing channels when data updates periodically and stakeholders need clear, non-technical takeaways alongside formal regression metrics. For non-linear responses or pricing elasticity curves, consider non-linear curve fitting or dedicated pricing models.