Data Analyst Interview
Menu
Data Analyst Interview
Menu

Python for Beginners: Analyse a Sales CSV

Python · First analysis

Learn Python for Beginners: Analyse a Sales CSV

Read a small CSV, apply a business rule and verify category totals using only Python’s standard library.

By Prakhar Shrivastava · Published 15 September 2026 · Practical learning guide

Start with a question you can check

You do not need a large dataset or several libraries to practise useful analysis. This exercise asks: what is the value of completed orders in each category? Every row is one order, amounts are whole US dollars (USD), and the data is invented. Returned and pending orders are excluded under the exercise’s definition.

The distinction between the data and the rule matters. A returned order is a valid record, but it is outside this particular calculation. In a real revenue report, clarify partial refunds, cancellations, taxes and the timing of recognition before reusing the rule.

Use Python 3 in a local editor or notebook. No extra package is required. Paste the full example into a new file and run it. The input is embedded in the code, so there is no download or file path to configure.

Run the complete example

import csv
from io import StringIO
from collections import defaultdict

data = """order_id,category,amount,status
101,Books,500,completed
102,Games,700,completed
103,Books,200,returned
104,Books,300,completed
105,Games,100,pending
"""
totals = defaultdict(int)
seen = set()
completed_count = 0
for row in csv.DictReader(StringIO(data)):
    order_id = row["order_id"]
    if order_id in seen:
        raise ValueError(f"Duplicate order: {order_id}")
    seen.add(order_id)
    if row["status"] not in {"completed", "returned", "pending"}:
        raise ValueError("Unexpected status")
    amount = int(row["amount"])
    if amount < 0:
        raise ValueError("Negative amount in this exercise")
    if row["status"] == "completed":
        totals[row["category"]] += amount
        completed_count += 1

for category, revenue in sorted(totals.items()):
    print(category, revenue)
print("Completed orders:", completed_count)
print("Total:", sum(totals.values()))

Compare the output with a hand calculation

Printed lineWhy it is correct
Books 800Completed orders 101 and 104: 500 + 300
Games 700Completed order 102 only
Completed orders: 3101, 102 and 104 satisfy the status rule
Total: 1500800 + 700

The input amount total is US$1,800. The returned US$200 order and pending US$100 order explain the US$300 difference from the completed total. This reconciliation is more informative than simply saying that the script ran successfully.

Alphabetical sorting makes the printed order predictable. It does not mean Books is always the highest-revenue category; the sorting rule is the category name. To rank by revenue, you would change that rule and define how to resolve ties.

Understand the pieces

csv.DictReader uses the header row as field names. CSV fields arrive as strings here, so the code explicitly converts each amount into an integer. StringIO lets the example read a string as a file-like object. For a real CSV file, use a context manager and open it with newline="", as shown in the Python CSV documentation.

The set called seen detects a repeated order ID. That check is appropriate only because we defined one row as one order. For an order-line file, several rows can legitimately share an order ID; you would need a line identifier or a different uniqueness rule.

The dictionary accumulates one total per category. Its default value is zero, so the first completed order can be added without first creating the category. The status check rejects unfamiliar values instead of silently excluding a misspelling such as “complete”.

Change the input and predict the answer

  1. Add order 106 for Books, amount 100, status completed. Expect Books 900, four completed orders and a total of 1,600.
  2. Repeat order 101 with a new amount. Expect a duplicate-order error. Investigate the record rather than deleting whichever row is inconvenient.
  3. Change an amount to an empty field. Integer conversion should fail; an unknown amount is not automatically zero.
  4. Change all statuses to pending. Expect no category lines, zero completed orders and a zero total.

The example deliberately uses whole US dollars (USD). For fractional currency, define an appropriate representation such as integer US cents or decimal arithmetic; do not casually round away differences. Also check blank categories, missing IDs and unexpected columns before adapting the script to messier data.

Once you can explain the loop, try the pandas worked example. Compare both implementations against the same expected totals. A useful interview explanation names the grain, the filter, the aggregation and the evidence that the result is correct.

Discover more from Data Analyst Interview

Subscribe now to keep reading and get access to the full archive.

Continue reading