Quick summary
Summarize this blog with AI
Analytics labels describe different questions and methods, not eight mutually exclusive job categories. A single project may use descriptive summaries, exploration, statistical inference, prediction, and domain-specific text or spatial methods. This guide retains those distinctions and uses small synthetic examples whose meaning can be checked.
The earlier version included skills.ai illustrations. The examples below are new, self-contained teaching material; they do not report findings about a real retailer, customer survey, or city. The existing publication attribution remains separate from these examples.
Choose the question before the tool
| Approach | Question | Typical limitation |
|---|---|---|
| Descriptive | What happened in the observed data? | A summary does not explain why |
| Inferential | What can a sample tell us about a target population? | Sampling and model assumptions matter |
| Exploratory | What patterns or data problems deserve investigation? | Discovered patterns need independent confirmation |
| Predictive | How well can we estimate an unseen outcome? | Prediction does not establish an intervention effect |
| Time series | How does a quantity evolve through time? | Order, dependence, seasonality and leakage matter |
| Diagnostic | Which explanations fit an observed problem? | Correlation or an outlier alone does not prove a cause |
| Text | What information can we extract from language? | Meaning depends on context and language |
| Spatial | How do location and distance affect the question? | Coordinate systems and privacy constraints matter |
1. Describe a dataset with defined units
Each tuple below is one fictional order: month, category, and gross amount in a single currency. Amounts are not unit counts or profit. The exercise assumes a complete, already-validated feed of included orders.
from collections import defaultdict
orders = [("2026-01", "A", 100), ("2026-01", "A", 50),
("2026-01", "B", 75), ("2026-02", "A", 80),
("2026-02", "B", 95)]
category_totals, monthly_totals = defaultdict(int), defaultdict(int)
for month, category, amount in orders:
category_totals[category] += amount
monthly_totals[month] += amount
grand_total = sum(category_totals.values())
shares = {key: value / grand_total for key, value in category_totals.items()}
print(dict(sorted(category_totals.items())))
print(dict(sorted(monthly_totals.items())))
print({key: round(value * 100, 1) for key, value in shares.items()})
Category totals are A: 230 and B: 170, out of 400. Their shares are 57.5% and 42.5%. Monthly totals are January 225 and February 175. The total declined by 50; these observations alone do not explain the decline. A bar chart of totals should be labeled as amounts, not as a percentage distribution unless the plotted values are percentages. If the grand total is zero, the share calculation needs an explicit undefined-result policy.
2. Infer beyond a sample only with justified assumptions
Suppose a prespecified sample of 100 independent observations from a normal population has mean 10, and the population standard deviation is known to be 2. The following standard-library calculation gives a 95% confidence interval for the population mean, approximately [9.6080, 10.3920].
from math import sqrt
from statistics import NormalDist
sample_mean, population_sd, sample_size = 10.0, 2.0, 100
margin = NormalDist().inv_cdf(.975) * population_sd / sqrt(sample_size)
print(round(sample_mean-margin, 4), round(sample_mean+margin, 4))
This is a known-variance teaching model, not a default recipe for a small satisfaction survey. The interval procedure’s repeated-sample coverage depends on the assumptions. A narrow interval does not repair a convenience sample, nonresponse bias, or dependent observations. Consult the worked inference guide for interpretation and alternatives.
3. Explore before making a confirmatory claim
Inspect row counts, types, missingness, duplicates, ranges, and distributions before fitting a model. Plotting two variables can reveal an unusual point or a change in spread, but it does not identify the point as an error automatically. Check the underlying record and measurement process.
In the order example, category A falls from 150 to 80 while B rises from 75 to 95. That decomposition suggests where to investigate. It does not prove that a promotion, price, or customer preference caused the change. Record hypotheses discovered during exploration and use suitable new evidence for confirmatory claims.
4. Predict held-out values and compare a baseline
This synthetic linear example includes all inputs and imports. Fit only the first four observations and evaluate on the last two. It illustrates a calculation, not a realistic estimate of commercial forecasting accuracy.
from statistics import mean
train_x, train_y = [1, 2, 3, 4], [3, 5, 7, 9]
test_x, test_y = [5, 6], [11, 13]
xbar, ybar = mean(train_x), mean(train_y)
denominator = sum((x-xbar)**2 for x in train_x)
if denominator == 0:
raise ValueError("training x needs variation")
slope = sum((x-xbar)*(y-ybar) for x, y in zip(train_x, train_y)) / denominator
intercept = ybar - slope*xbar
predictions = [intercept + slope*x for x in test_x]
model_mae = mean(abs(actual-predicted) for actual, predicted in zip(test_y, predictions))
baseline_mae = mean(abs(actual-ybar) for actual in test_y)
print(predictions, model_mae, baseline_mae)
The predictions are [11.0, 13.0], model mean absolute error is 0.0, and the training-mean baseline error is 6.0. The data follows an exact constructed line, so a perfect result is expected and does not demonstrate generalization to real data. Prediction from an observational relationship also does not tell you what would happen if you intervened on x.
5. Preserve time order and define the forecast horizon
A time-series analysis may describe trend and seasonality or forecast future values. Decomposition separates modeled components; it is not itself a forecast. Keep future observations out of training features and fit transformations using only available history.
from statistics import mean
train = [10, 12, 11, 13]
future = [14, 12]
forecast = [train[-1]] * len(future)
mae = mean(abs(actual-predicted) for actual, predicted in zip(future, forecast))
print(forecast, mae)
A last-observation baseline predicts [13, 13] and has MAE 1.0 on this tiny fixture. A real comparison should evaluate relevant horizons over multiple time cutoffs and consider seasonality, dependence, and uncertainty. Two months of order totals are not enough evidence to claim an annual seasonal pattern.
6. Investigate competing explanations
For declining sales, verify the feed and definition first. Then decompose compatible quantities such as order count and average order amount, and inspect segments, calendar effects, prices, availability, and releases. State which observation would support or weaken each explanation.
An outlier can be a data error, a genuine rare event, or evidence that the model is incomplete. A fitted line and a distant point do not establish root cause. Causal claims require an appropriate experimental or observational design with defensible assumptions.
7. Treat word counts as word counts
The example counts case-folded whitespace tokens. It is deliberately not a sentiment classifier.
from collections import Counter
reviews = ["good delivery", "not good", "late delivery"]
counts = Counter(word for review in reviews for word in review.casefold().split())
print(dict(sorted(counts.items())))
The counts are delivery: 2, good: 2, late: 1, not: 1. Counting “good” twice would misrepresent the meaning of “not good” if interpreted as two positive reviews. A real text model needs an appropriate label definition, evaluation set, language coverage, and analysis of negation, context, and errors.
8. State the coordinate system and distance meaning
Longitude and latitude are angular coordinates. Do not treat a one-degree difference as a universal meter distance. The spherical great-circle calculation below uses fictional points on the equator and an explicitly chosen Earth radius.
from math import radians, sin, cos, asin, sqrt
lat1, lon1, lat2, lon2 = map(radians, [0, 0, 0, 1])
a = sin((lat2-lat1)/2)**2 + cos(lat1)*cos(lat2)*sin((lon2-lon1)/2)**2
distance_km = 2 * 6371.0 * asin(sqrt(min(1.0, max(0.0, a))))
print(round(distance_km, 3))
The approximate surface distance is 111.195 km under that spherical model. It is not road distance, travel time, or a survey-grade ellipsoidal measurement. Use an appropriate coordinate reference system and distance method for the question. Avoid exposing precise personal locations when aggregated or synthetic geography is sufficient.
Connect the analysis to a decision
Prescriptive work adds objectives, constraints, and tradeoffs to recommend an action; it is not automatically produced by a predictive model. For any approach, state the input grain, missing-data policy, expected output, assumptions, and limits. A beginner can demonstrate strong analytical judgment by producing one reproducible answer and explaining what it does and does not establish.