←Back to the bookChapter 157 · Report 3 · Analytical Report
▶ Open in Colab⬇ Download notebookView on GitHub
Chapter 157 · Communicating Results · Report 3 of 3

Analysis for the Analytical Report: Drivers of Customer Satisfaction

This notebook fits the regression and builds the results figures and table. It stops at the evidence; the full written study is a separate, human-authored Word document a statistician composes for a non-technical reader. Download it from the chapter.
In [1]:
import numpy as np, pandas as pd
import matplotlib as mpl, matplotlib.pyplot as plt
# A clean house style for report-ready figures: no chartjunk, strong titles, muted grid.
mpl.rcParams.update({"figure.dpi":110,"font.size":11,"axes.spines.top":False,"axes.spines.right":False,
    "axes.grid":True,"grid.alpha":0.22,"axes.titleweight":"bold","axes.titlesize":12.5,
    "axes.titlelocation":"left","axes.titlepad":10})
ROSE, INK, MUT, GR, RD = "#be123c", "#1a2138", "#64748b", "#16a34a", "#dc2626"
BASE = "https://raw.githubusercontent.com/johnfisher-ai/Statistics-Data-Science-AI-Visual-Book/main/data/"
fn = "communicating-insights--company-data.xlsx"
def load(sheet):
    try: return pd.read_excel("../../data/" + fn, sheet_name=sheet)
    except FileNotFoundError: return pd.read_excel(BASE + fn, sheet_name=sheet)
import statsmodels.formula.api as smf

Step 1 · Fit the model¶

Regress overall satisfaction on four candidate drivers. The coefficients say how many points of satisfaction each one-point improvement in a driver buys, holding the others fixed.

In [2]:
survey = load("Survey")
model = smf.ols("satisfaction ~ ease_of_use + support_quality + price_fairness + wait_time", survey).fit()
coefs = model.params.drop("Intercept").sort_values(ascending=False)
print(f"R-squared {model.rsquared:.3f}  | mean satisfaction {survey.satisfaction.mean():.1f}")
print(coefs.round(2).to_string())
R-squared 0.843  | mean satisfaction 66.1
ease_of_use        3.82
support_quality    2.37
price_fairness     1.51
wait_time         -0.90

Step 2 · Results figures¶

A coefficient plot ranks the drivers by impact, and a scatter shows the strongest one against satisfaction. Both carry titles that state the finding.

In [3]:
fig_coef, ax = plt.subplots(figsize=(7.4, 3.0))
cvals = coefs.sort_values()
ax.barh(cvals.index.str.replace("_"," "), cvals.values, color=[RD if v<0 else ROSE for v in cvals.values])
ax.axvline(0, color=INK, lw=1); ax.set_title("Ease of use is the biggest driver; long waits hurt")
ax.set_xlabel("points of satisfaction per 1-point change in driver"); ax.grid(axis="y", visible=False)
plt.tight_layout(); plt.show()

fig_sc, ax = plt.subplots(figsize=(6.6, 3.2))
ax.scatter(survey.ease_of_use, survey.satisfaction, s=14, alpha=0.4, color=ROSE)
b0, b1 = np.polyfit(survey.ease_of_use, survey.satisfaction, 1)
xs = np.array([survey.ease_of_use.min(), survey.ease_of_use.max()])
ax.plot(xs, b0*xs+b1, color=INK, lw=2)
ax.set_title("Satisfaction rises steadily with ease of use"); ax.set_xlabel("ease of use (1-10)"); ax.set_ylabel("satisfaction (0-100)")
plt.tight_layout(); plt.show()
No description has been provided for this image
No description has been provided for this image

Step 3 · The coefficient table for the report¶

The regression table with standard errors and p-values is the backbone of the written study. Display it cleanly here; the statistician reproduces it in the document and explains, in plain words, what each number means.

In [4]:
tbl = pd.DataFrame({"Driver":[i.replace("_"," ") for i in model.params.index],
                   "Coefficient":[f"{v:+.2f}" for v in model.params.values],
                   "Std. error":[f"{v:.2f}" for v in model.bse.values],
                   "p-value":[f"{v:.3f}" for v in model.pvalues.values]})
tbl
Out[4]:
Driver Coefficient Std. error p-value
0 Intercept +28.03 1.33 0.000
1 ease of use +3.82 0.12 0.000
2 support quality +2.37 0.11 0.000
3 price fairness +1.51 0.11 0.000
4 wait time -0.90 0.11 0.000

From analysis to report¶

This notebook is the analysis: the regression, the coefficient table, and the two figures. The finished study is a separate, human-authored Word document, a statistician writing for a non-technical reader, who states the headline first, translates the coefficients into plain terms (each point of ease of use is worth about 3.8 points of satisfaction), and is honest that survey associations are not proven causes. Download it from the chapter to see the write-up these numbers deserve.

←Back to the bookChapter 157 · Report 3 · Analytical Report