Kaggle’s Chocolate Sales dataset is a clean, well-structured dataset with 3,282 transactions across 6 countries, 18 products, and 25 sales representatives — perfect for both visual exploration and predictive modeling.
I built two notebooks on this dataset: one focused on exploratory data analysis (EDA) and another on ML & deep learning prediction. Here’s what I found, how I built it, and what you can learn from each.
The Dataset at a Glance
| Column | Type | Example |
|---|---|---|
| Sales Person | Categorical (25 unique) | Kelci Walkden |
| Country | Categorical (6 unique) | Australia, India, UK, USA, Canada, New Zealand |
| Product | Categorical (18 unique) | 85% Dark Bars, Milk Bars, Drinking Coco |
| Date | Datetime | 01/01/2022 – 31/12/2024 |
| Amount | Currency string | “$5,320.00” |
| Boxes Shipped | Integer | 42 |
The Amount field comes as a formatted currency string — stripping $ and , is the first cleaning step. Dates are in DD/MM/YYYY format, which catches many people off guard when using pd.to_datetime with default settings.
EDA Notebook: Visual Exploration with Plotly
View the full EDA notebook on Kaggle →
The EDA notebook covers 12 sections, all with interactive Plotly charts using a chocolate-inspired color palette (#5B3A29, #8B6914, #D2691E, #CD853F, #DEB887).
Key Findings
Revenue Distribution: The data is right-skewed — most transactions cluster in the low-to-mid range, with a long tail of high-value sales. This is typical for B2B sales data and important to know before modeling (it tells us mean ≠ median).
Country Analysis: Revenue varies significantly across markets. We looked at both total revenue (market size) and average transaction size (spending intensity) — a country can rank high in one but not the other.
The Surprising Correlation: Revenue vs. Boxes Shipped has a correlation of -0.013 — essentially zero. Higher volume does not mean higher revenue. This means pricing is highly variable across products and markets, and any ML model that relies too heavily on Boxes Shipped will miss the real signal.
Product × Country Heatmap: Cultural preferences for chocolate vary. The heatmap reveals which products sell best in which countries — useful for localized product strategies. Sunburst and treemap charts break down the top 10 sales people by their country and product mix.
Seasonality: Monthly and day-of-week patterns were analyzed. Holiday months (February, April, December) were highlighted to check for Valentine’s Day, Easter, and Christmas effects.
ML & Deep Learning Notebook: 4 Models Compared
View the full ML notebook on Kaggle →
The goal: predict Amount (revenue) from all other features. We built 4 models progressively, from a simple baseline to a neural network.
Feature Engineering (26 Features)
Raw data rarely works well for ML. Here’s what we built:
| Feature Type | Count | Examples |
|---|---|---|
| Date decomposition | 7 | Year, Month, DayOfWeek, Quarter, WeekOfYear, IsWeekend |
| Cyclical encoding | 6 | sin/cos of Month, DayOfWeek, DayOfMonth |
| Label encoding | 4 | Sales Person, Country, Product, Country×Product |
| Target encoding | 4 | Mean revenue per category |
| Frequency encoding | 3 | How often each category appears |
| Boxes features | 3 | Raw, log-transformed, squared |
Cyclical encoding deserves special mention: if Month is encoded as 1–12, the model thinks December (12) is far from January (1). Using sin(2π × month/12) and cos(2π × month/12) preserves the circular relationship.
Model 1: Ridge Regression (Baseline)
Linear regression with L2 regularization (alpha=1.0). Features are standardized with StandardScaler before training — this is critical for linear models where feature scales affect coefficient magnitudes.
This sets the floor: any model that can’t beat a straight line isn’t worth the complexity.
Model 2: Random Forest
An ensemble of 300 decision trees, each trained on a random subset of data and features:
n_estimators=300, max_depth=12, min_samples_leaf=5,
max_features=0.7, n_jobs=-1
max_depth=12 prevents individual trees from memorizing the training data. min_samples_leaf=5 ensures each leaf has enough data to make a reliable prediction. max_features=0.7 means each tree only sees 70% of features, forcing diversity.
Model 3: XGBoost
Gradient boosting — the state-of-the-art for tabular data:
n_estimators=1000, learning_rate=0.05, max_depth=6,
subsample=0.8, colsample_bytree=0.8,
reg_alpha=0.1, reg_lambda=1.0,
min_child_weight=10, tree_method='hist'
Unlike Random Forest (parallel trees), XGBoost builds trees sequentially — each new tree corrects the mistakes of previous ones. learning_rate=0.05 means each tree contributes modestly, requiring more trees (1000) but achieving higher precision. Early stopping prevents overfitting.
Model 4: Neural Network (Keras)
A feedforward network with 3 hidden layers:
Input(26) → Dense(256) + BatchNorm + ReLU + Dropout(0.3)
→ Dense(128) + BatchNorm + ReLU + Dropout(0.2)
→ Dense(64) + BatchNorm + ReLU + Dropout(0.1)
→ Dense(1)
Training configuration:
- Optimizer: Adam (
lr=1e-3) - Loss: MSE
- Callbacks: EarlyStopping (
patience=20), ReduceLROnPlateau (factor=0.5, patience=10, min_lr=1e-6) - Batch size: 64, max 200 epochs
BatchNormalization normalizes each layer’s input, dramatically speeding up convergence. Dropout randomly disables neurons during training — effectively training an ensemble of sub-networks within one model.
Ensembles
Three ensemble strategies were tested:
- Simple average — equal weight to all 4 models
- Weighted average — weights proportional to inverse MAE (better model → higher weight)
- Top-3 blend — average of the 3 best models, dropping the weakest
Evaluation: 5-Fold Cross-Validation
All models evaluated with the same 5-fold CV split (KFold, shuffle=True, seed=42). Three metrics reported:
- MAE — average prediction error in dollars
- RMSE — penalizes large errors more heavily
- R² — 1.0 = perfect, 0.0 = predicting the mean
Results Visualization
The notebook includes:
- MAE/R² bar charts comparing all models side by side
- Predicted vs Actual scatter plots for each model (with perfect-prediction reference line)
- Error distribution histograms — overlaid for all 4 models to compare error shapes
- XGBoost feature importance — top 15 features ranked by split importance
Key Takeaway
Tree-based models (XGBoost, Random Forest) outperform both linear regression and neural networks on this dataset. This is consistent with Grinsztajn et al. (NeurIPS 2022), which showed tree-based models dominate on tabular data under ~50K rows. Feature engineering — especially target encoding — provides more lift than switching model architectures.
Try It Yourself
Both notebooks are public and ready to fork:
- EDA: Chocolate Sales EDA: Who Sells the Most Chocolate?
- ML & DL: Predicting Chocolate Sales with ML & Deep Learning
The dataset is small enough to run entirely on CPU in under 5 minutes. No GPU needed.
FAQ
What Python libraries are needed for these notebooks?
Both notebooks use pandas, numpy, and plotly for visualization. The ML notebook additionally requires scikit-learn, xgboost, and tensorflow (Keras). All are pre-installed in the Kaggle environment — no extra setup needed.
Why does the neural network underperform XGBoost on this dataset?
With only 3,282 rows, there isn’t enough data for a neural network to learn complex patterns that tree-based models capture naturally. Neural networks typically need 50K+ rows to outperform gradient boosting on tabular data. The 2022 NeurIPS benchmark by Grinsztajn et al. confirmed this finding across 45 datasets.
Can I use these notebooks for a different sales dataset?
Yes. The feature engineering pipeline is generic — date decomposition, cyclical encoding, target encoding, and frequency encoding work on any tabular dataset with categorical and datetime columns. Just swap the CSV path and column names.
Did you find this helpful?
Your support keeps this blog running and ad-free content coming.
☕ Buy me a coffeeMost Popular Posts
- Custom Metaclass in Python: 43% Faster Validation (12,929 views)
- yfinance Alternatives 2026: 7 Free APIs Compared (978 views)
- Python match-case: 7 Patterns That Beat if-elif Chains (975 views)
- YOLOv8 INT8 Quantization: 4x Faster on Jetson Orin (864 views)
- PaddleOCR vs EasyOCR vs Tesseract: Why PaddleOCR Is Slower (678 views)