🔥 0
0
Lesson 1 of 8 20 min +150 XP

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.
columnmeaningexample
order_idunique id for the orderORD10001
customer_idwho bought itCUST042
product_idwhat was boughtPRD017
categoryproduct categoryElectronics
brandproduct brandBoat
priceprice per unit in ₹1299.00
quantityunits in this line2
order_datedate of purchase2024-01-02
cityshipping cityMumbai
customers.csv — one row per customer.
columnmeaningexample
customer_idunique customer idCUST042
namecustomer namePriya Nair
signup_dateaccount created2023-11-02
segmentRegular / PremiumPremium
cityhome cityMumbai
products.csv — one row per product in the catalog.
columnmeaningexample
product_idunique product idPRD017
nameproduct nameBoat Rockerz 255 Earphones
categorycategoryElectronics
brandbrandBoat
pricelist price in ₹1299.00
ratingavg rating (1–5)4.2
descriptionfree-text blurbWireless neckband earphones with 40 hour playback...
tagsspace-separated tagswireless 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.

ShopKart: raw data to GenAI Raw CSVs orders customers products Pandas clean, join, group EDA + Features RFM table ML models recommender churn GenAI embeddings RAG assistant Each lesson moves one box to the right — same dataset throughout

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.

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.