Python & the E-Commerce Dataset
Imagine you just joined ShopKart, a fast-growing Indian e-commerce store selling everything from kurtas to Bluetooth earbuds across Mumbai, Delhi, Bengaluru and beyond. On your first day, the data lead drops three CSV files on you and says: "Tell me which categories make the most money, why customers leave, and can we build a smart product assistant?"
That single ask is a whole data-and-ML journey. Over this course we'll turn those raw CSVs into a product recommender, a churn predictor, and a GenAI shopping assistant — all in Python. This first lesson gets the data loaded and gives you the map for everything ahead.
The ShopKart dataset
Everything we build uses three tables. Keep this schema handy — we reference it in every lesson.
orders.csv — one row per line item purchased.| column | meaning | example |
|---|---|---|
| order_id | unique id for the order | ORD10001 |
| customer_id | who bought it | CUST042 |
| product_id | what was bought | PRD017 |
| category | product category | Electronics |
| brand | product brand | Boat |
| price | price per unit in ₹ | 1299.00 |
| quantity | units in this line | 2 |
| order_date | date of purchase | 2024-01-02 |
| city | shipping city | Mumbai |
| column | meaning | example |
|---|---|---|
| customer_id | unique customer id | CUST042 |
| name | customer name | Priya Nair |
| signup_date | account created | 2023-11-02 |
| segment | Regular / Premium | Premium |
| city | home city | Mumbai |
| column | meaning | example |
|---|---|---|
| product_id | unique product id | PRD017 |
| name | product name | Boat Rockerz 255 Earphones |
| category | category | Electronics |
| brand | brand | Boat |
| price | list price in ₹ | 1299.00 |
| rating | avg rating (1–5) | 4.2 |
| description | free-text blurb | Wireless neckband earphones with 40 hour playback... |
| tags | space-separated tags | wireless bluetooth earphones neckband sports battery |
The full journey
Before touching code, see where we're headed. Raw data flows left to right, gaining structure and intelligence at each step.
Download the dataset
Grab the three CSVs before you write any code. Put them in the same folder as your notebook or script — every lesson in this course loads them with a plain relative filename.
- orders.csv — 12,480 line items
- customers.csv — 1,500 customers
- products.csv — 600 products
On the command line you can pull all three at once:
curl -O https://resources.criodo.com/data/shopkart/orders.csv
curl -O https://resources.criodo.com/data/shopkart/customers.csv
curl -O https://resources.criodo.com/data/shopkart/products.csv
The data is synthetic — generated to look and behave like a real Indian e-commerce catalog, with the messiness left in (missing brands, missing segments, a long tail of prices). Nobody's real purchase history is in here.
Setting up your tools
You need Python 3.x and a few libraries. Install them once with pip.
pip install pandas numpy matplotlib seaborn scikit-learn
# For the GenAI lessons later:
pip install sentence-transformers openai anthropic faiss-cpu
- pandas — the workhorse for tabular data (think spreadsheets in code).
- numpy — fast numerical arrays; pandas is built on it.
- matplotlib / seaborn — plotting for exploratory analysis.
- scikit-learn — classic machine learning models and utilities.
Lessons 1–7 run entirely on your own machine and cost nothing. Lesson 8 (the RAG assistant) calls a hosted LLM, so it needs an API key from Anthropic or OpenAI — a few cents for the requests in that lesson. That lesson explains how to set one up when you get there.
Every output printed in this course was produced by actually running the code against those CSVs on pandas 3.0 and scikit-learn 1.9. If you're on pandas 2.x a few cosmetic details differ — most visibly, text columns show up as object rather than str in .info().
A note for professionals moving into data work: most teams run this inside a Jupyter notebook or Google Colab, where you can run code cell by cell and see tables render inline. The code below works the same in a plain .py script.
Loading the CSVs
pandas.read_csv reads a file into a DataFrame — a 2D table with labelled columns and an index. We tell it which column holds dates so pandas parses them as real datetimes, not strings.
import pandas as pd
orders = pd.read_csv("orders.csv", parse_dates=["order_date"])
customers = pd.read_csv("customers.csv", parse_dates=["signup_date"])
products = pd.read_csv("products.csv")
print(orders.shape) # (rows, columns)
print(customers.shape)
print(products.shape)
(12480, 9)
(1500, 5)
(600, 8)
So ShopKart has 12,480 order line items from 1,500 customers across 600 products. Small enough to explore comfortably, realistic enough to be interesting.
First look: head()
.head(n) shows the first n rows (default 5). It's the first thing you run on any new dataset.
orders.head()
order_id customer_id product_id category brand price quantity order_date city
0 ORD10001 CUST042 PRD017 Electronics Boat 1299.0 1 2024-01-01 Mumbai
1 ORD10002 CUST119 PRD221 Fashion Levis 2199.0 1 2024-01-01 Mumbai
2 ORD10003 CUST042 PRD088 Home & Kitchen Milton 649.0 2 2024-01-02 Mumbai
3 ORD10004 CUST311 PRD500 Electronics Samsung 18999.0 1 2024-01-02 Mumbai
4 ORD10005 CUST008 PRD156 Beauty Lakme 399.0 3 2024-01-02 Bengaluru
Already you can read a story: customer CUST042 bought Boat earphones and then a Milton bottle a day later — a repeat customer in Mumbai.
Structure: info()
.info() reports each column's dtype (data type) and how many non-null values it has. This is where you catch missing data and wrong types early.
orders.info()
<class 'pandas.DataFrame'>
RangeIndex: 12480 entries, 0 to 12479
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 order_id 12480 non-null str
1 customer_id 12480 non-null str
2 product_id 12480 non-null str
3 category 12480 non-null str
4 brand 12360 non-null str
5 price 12480 non-null float64
6 quantity 12480 non-null int64
7 order_date 12480 non-null datetime64[us]
8 city 12480 non-null str
dtypes: datetime64[us](1), float64(1), int64(1), str(6)
memory usage: 877.6 KB
Two things to notice. order_date is a proper datetime64 (good — our parse_dates worked). And brand has only 12,360 non-null values out of 12,480, so 120 rows are missing a brand. We'll handle that in the next lesson.
Summary statistics: describe()
.describe() gives count, mean, standard deviation, min, max and quartiles for numeric columns. It's your quick sanity check on scale and outliers.
orders[["price", "quantity"]].describe()
price quantity
count 12480.000000 12480.000000
mean 1274.489744 1.663381
std 1728.344159 1.144670
min 149.000000 1.000000
25% 440.000000 1.000000
50% 776.000000 1.000000
75% 1555.000000 2.000000
max 18999.000000 8.000000
The average line item is around ₹1,274, but the median is only ₹776 and the max is ₹18,999 — a premium smartphone dragging the mean above the middle. Most orders are 1–2 units. This one command tells you the price range spans two orders of magnitude, which will matter when we scale features for machine learning later.
You can describe text columns too, which reports counts and the most frequent value:
orders[["category", "city"]].describe()
category city
count 12480 12480
unique 6 8
top Electronics Mumbai
freq 4068 3048
Electronics is the most common category (4,068 line items) and Mumbai the most common city (3,048). Great starting hypotheses to dig into during exploratory analysis.
Selecting columns and rows
Two quick idioms you'll use constantly. Grab a single column with bracket notation, and filter rows with a boolean condition.
# One column (a Series)
orders["city"].head(3)
# Rows where price is above 5000
orders[orders["price"] > 5000].head(3)
0 Mumbai
1 Mumbai
2 Mumbai
Name: city, dtype: str
order_id customer_id product_id category brand price quantity order_date city
3 ORD10004 CUST311 PRD500 Electronics Samsung 18999.0 1 2024-01-02 Mumbai
71 ORD10044 CUST386 PRD500 Electronics Samsung 18999.0 2 2024-01-04 Kolkata
355 ORD10227 CUST1471 PRD441 Electronics Sony 8613.0 1 2024-01-08 Hyderabad
We'll go much deeper on selection and filtering in the next lesson — for now, just know that a DataFrame behaves like a queryable table.
On the job
In a real analytics or data-science role, head(), info(), and describe() are the first three commands you run on any new dataset — before writing a single line of analysis. They answer: How big is it? What are the types? Is anything missing or absurd? Skipping this step is how people ship reports built on a column that was silently parsed as text, or an outlier that skews every average. Treat these three as your pre-flight checklist.
Key takeaways
- ShopKart is our running dataset:
orders,customers,products— three linked CSVs in ₹ INR. - Install the stack with pip:
pandas,numpy,matplotlib/seaborn,scikit-learn, plus GenAI libs later. read_csv(..., parse_dates=[...])loads a DataFrame and parses dates correctly.head()previews rows,info()reveals dtypes and missing values,describe()summarizes distributions.- We already spotted 120 missing brands and a wide price range — real issues we'll fix as we build toward a recommender, a churn model, and a GenAI assistant.