Populate a Shipping Database with Python
Write a Python ETL script to load three CSV files into a SQLite database.
Introduction
30 Second Summary
Every company has that one task where data lives in multiple messy spreadsheets and someone needs to combine it all into a single source of truth. Shipping teams deal with this constantly.
In this project, you will write a Python script that reads three CSV spreadsheets with different formats, cleans and merges the data, and loads everything into a SQLite database.
What You'll Build
Run your script once and watch it process over 100 rows of shipping data across three files, transforming messy columns and merging incomplete records into a single, queryable database in seconds.
By the end of this project, you'll have:
- A working ETL script that reads three spreadsheets, cleans whitespace issues, and loads everything into a database with a single command.
- Hands-on experience joining incomplete datasets by matching shared identifiers and counting rows to calculate quantities.
- A fully populated SQLite database you can open and query to see all shipments unified in one table, with a printed row count confirming your data is clean and complete.
- Secret Mission: Add a verification summary that prints shipment statistics after populating the database.
Are there any prerequisites?
None. This guide includes full setup instructions. You just need a Google account. All project files are cloned from a GitHub repository directly inside Google Colab.
Before We Start
Before we dive in, let's lock in what you're about to build and why it matters.
Set Up Python and Your Workspace
Set Up Google Colab and Your Workspace
To write a script that processes shipping data, you need Python and access to your project files. Google Colab gives you both in the browser — Python is pre-installed and you can clone your repository in one command.
In this step, you will open a new Colab notebook, clone the project repository, and verify that the data files are ready to use.
In this step, get ready to:
- Open a new notebook in Google Colab.
- Clone the project repository into your Colab environment.
- Verify the data files and set up file paths.
Open a new notebook in Google Colab
- Open your browser and go to colab.research.google.com.
- Sign in with your Google account if prompted.
- Click New notebook to create a blank notebook.
You should see an empty code cell ready for input. The notebook is named Untitled0.ipynb by default.
- Click the notebook title at the top left and rename it to populate.ipynb.
What is Google Colab?
Google Colab is a free, browser-based environment that lets you write and run Python code in cells. Each cell runs independently, so you can build your script piece by piece and see results instantly.
Colab comes with Python and common libraries pre-installed. No setup on your local machine required.
Clone the project repository
Your project files (CSV spreadsheets and the database) live in a GitHub repository. You will clone it into the Colab runtime so your notebook can access them.
- Clone the repository into your Colab environment by pasting this command into the first code cell and running it:
!git clone https://github.com/Athman-Dodoe/forage-walmart-task-4.git
What does the ! do?
The ! prefix tells Colab to run the command in the system shell instead of as Python code. git clone downloads the full repository into a folder called forage-walmart-task-4 inside Colab's /content/ directory.
You should see output ending with done. confirming the clone succeeded.
- Verify the data files exist by running this command in a new cell:
!ls forage-walmart-task-4/data/
You should see four files listed: shipping_data_0.csv, shipping_data_1.csv, shipping_data_2.csv, and shipping_data.db.
What are these files?
The three CSV files contain raw shipping data from different sources. Each spreadsheet has a different structure, which is why you need a script to combine them.
The .db file is a SQLite database with a pre-created table schema. Your script will insert the cleaned data into this database.
🙋♀️ Not seeing the files?
Make sure the clone command finished without errors. If you see fatal: destination path already exists, the repo was already cloned in a previous cell run. That is fine — your files are already there.
Help me fix my git clone in Colab
Set up your file paths
Every code cell in your notebook will need to know where the data files live. Setting up path variables now means you can reference them throughout the rest of the project.
- Add the file path configuration by pasting this code into a new cell and running it:
import csv
import sqlite3
import os
# Project folder path inside Colab
folder_name = "forage-walmart-task-4"
project_dir = os.path.join("/content", folder_name)
# File paths
db_path = os.path.join(project_dir, "data", "shipping_data.db")
csv0_path = os.path.join(project_dir, "data", "shipping_data_0.csv")
csv1_path = os.path.join(project_dir, "data", "shipping_data_1.csv")
csv2_path = os.path.join(project_dir, "data", "shipping_data_2.csv")
print("Paths configured!")
What does this code do?
os.path.join builds file paths that work on any operating system. Each variable stores the full path to one of the three CSV files or the database inside the cloned repo.
Running this cell also imports csv, sqlite3, and os — the three standard library modules you will use throughout this project.
You should see Paths configured! printed below the cell.
Seeing a ModuleNotFoundError?
The csv, sqlite3, and os modules are part of Python's standard library and come pre-installed in Colab. If you see an import error, check for typos in the module names.
Help me fix an import error in Colab
Your workspace is ready to go. Next up, you will write code that reads the shipping CSV files and prints their contents so you can understand the data you are working with.
Read and Print Shipping Data
Your Colab notebook is connected and the project files are cloned. Now it's time to look at the actual data.
Before you can insert shipping data into a database, you need to understand what each spreadsheet contains. The three CSV files in your data folder have different column structures that will affect how you process them.
In this step, get ready to:
- Read all three shipping CSV files and examine their contents.
- Inspect the database schema to understand the target table format.
Write code to read the CSV files
Python's built-in csv module can read CSV rows as dictionaries, where each column header becomes a key. This lets you see the exact field names and values without guessing.
- Read the first 3 rows of each CSV file by pasting this code into a new cell and running it:
# Print first 3 rows of each CSV
for path, label in [(csv0_path, "CSV 0"), (csv1_path, "CSV 1"), (csv2_path, "CSV 2")]:
print(f"--- {label} ---")
with open(path, newline="") as f:
reader = csv.DictReader(f)
for i, row in enumerate(reader):
if i >= 3:
break
print(row)
What does this code do?
csv.DictReader(f) reads each CSV row as a Python dictionary. The first row of the file becomes the dictionary keys (column names), and each subsequent row becomes values mapped to those keys.
The loop prints the first 3 rows from each of the three files so you can compare their structures side by side.
Before you run this cell, what format do you expect each row to be printed in?
You should see each row printed as a Python dictionary with column names as keys and cell values as values. The output starts with --- CSV 0 --- followed by three dictionary rows.
Seeing a FileNotFoundError?
- Make sure you ran the imports and file paths cell from Step 1 first. Colab cells share state, so variables like csv0_path must be defined before you can use them.
- Confirm the repo was cloned by running !ls /content/forage-walmart-task-4/data/ in a new cell.
Help me fix a FileNotFoundError in my Colab notebook
Compare the CSV structures
Look at the output from all three CSV files. You will notice the column structures are very different between them.
Inspect the database schema
Now you know what the source data looks like. The next question is: what format does the database expect? You can query the database's metadata to find out.
What are the differences between the three files?
- CSV 0 has all the fields you need: origin_warehouse, destination_store, product, on_time, product_quantity, and driver_identifier. Each row is a complete shipment record.
- CSV 1 only has shipment_identifier, product, and on_time. It is missing origin, destination, and driver info.
- CSV 2 only has shipment_identifier, origin_warehouse, destination_store, and driver_identifier. It is missing the product info.
CSV 1 and CSV 2 share a shipment_identifier column. This is the key you will use later to join them together into complete records.
- Inspect the database schema by pasting this code into a new cell and running it:
# Inspect database schema
con = sqlite3.connect(db_path)
cur = con.cursor()
cur.execute("SELECT name, sql FROM sqlite_master WHERE type='table'")
for row in cur.fetchall():
print(row)
con.close()
What does this code do?
sqlite3.connect(db_path) opens a connection to the SQLite database file. The sqlite_master table is a built-in SQLite table that stores the schema of every table in the database.
Querying it with SELECT name, sql returns the table name and the full CREATE TABLE statement that defines its columns. This tells you exactly what columns the database expects.
What columns do you think the database table will have, based on what you saw in the CSV files?
You should see a tuple showing the table name shipments and its CREATE TABLE statement listing columns: origin_warehouse, destination_store, product, on_time, product_quantity, and driver_identifier.
Not seeing the schema output?
- Make sure the database inspection code is in its own cell, not accidentally merged with the CSV reading cell.
- Confirm that shipping_data.db exists by running !ls /content/forage-walmart-task-4/data/ in a new cell.
Help me debug why my sqlite3 query isn't printing results
You may also notice some dictionary keys have trailing spaces (like 'driver_identifier ' instead of 'driver_identifier'). That is a data quality issue you will fix in a later step.
Now you know exactly what the source data looks like and what format the database expects. Next up, you will start inserting data from the simplest spreadsheet first.
Insert Spreadsheet 0 Into the Database
In the previous step you printed sample rows and discovered the database schema. Now it is time to write real data into that database.
Spreadsheet 0 already contains every column the shipments table expects, so it is the simplest starting point. You will write a parameterized INSERT statement, run it against the real CSV, and discover first-hand what happens when real-world data does not match the tidy column names you expect.
In this step, get ready to:
- Write a parameterized INSERT statement that maps CSV columns to database columns.
- Discover and fix a hidden whitespace problem in the CSV data.
- Confirm that all spreadsheet 0 rows are stored in the database.
Write the insert logic for spreadsheet 0
The exploratory print code from the previous step served its purpose. Time to replace it with production logic that actually writes rows into the database.
- In your notebook, the imports and path variables from Step 1 are still available. Create a new cell and paste the insert logic:
con = sqlite3.connect(db_path)
cur = con.cursor()
# --- Insert spreadsheet 0 ---
with open(csv0_path, newline="") as f:
reader = csv.DictReader(f)
for row in reader:
cur.execute(
"INSERT INTO shipments (origin_warehouse, destination_store, product, on_time, product_quantity, driver_identifier) VALUES (?, ?, ?, ?, ?, ?)",
(
row["origin_warehouse"],
row["destination_store"],
row["product"],
row["on_time"],
row["product_quantity"],
row["driver_identifier"],
),
)
con.commit()
con.close()
What does this code do?
- sqlite3.connect(db_path) opens a connection to your existing shipping_data.db file.
- csv.DictReader reads each CSV row as a dictionary, using the first row of the file as keys.
- The ? placeholders in the INSERT statement are filled by the tuple of values. This prevents SQL injection and handles special characters safely.
- con.commit() saves all the inserted rows to disk. Without it, nothing is actually written.
Run the cell to execute the insert logic.
Run the script and observe the whitespace problem
Before you run this, what do you think will happen? Will the script insert all the rows cleanly, or will something go wrong?
Before you run this, what do you think will happen? Will the script insert all the rows cleanly, or will something go wrong?
You will see a KeyError traceback. The cell crashes because it cannot find the key driver_identifier in the dictionary.
Why did this happen?
The CSV file has trailing spaces on its column headers. When csv.DictReader reads the file, the last column becomes the key "driver_identifier " (with a space at the end) instead of "driver_identifier". Your code asks for row["driver_identifier"] (no space), so Python raises a KeyError.
This is a common real-world data quality issue. Spreadsheet exports and hand-edited CSVs often carry invisible whitespace that breaks code relying on exact key matches.
Fix the whitespace issue and convert data types
The fix is to strip whitespace from every key and every value as you read each row. You also need to convert the on_time string ("true"/"false") into a proper Python boolean, and product_quantity into an integer.
- Create a new cell and paste the fixed insert logic. This replaces the code from the previous cell:
con = sqlite3.connect(db_path)
cur = con.cursor()
# --- Insert spreadsheet 0 (with whitespace fix) ---
with open(csv0_path, newline="") as f:
reader = csv.DictReader(f)
for row in reader:
# Strip whitespace from keys and values
clean = {k.strip(): v.strip() for k, v in row.items()}
cur.execute(
"INSERT INTO shipments (origin_warehouse, destination_store, product, on_time, product_quantity, driver_identifier) VALUES (?, ?, ?, ?, ?, ?)",
(
clean["origin_warehouse"],
clean["destination_store"],
clean["product"],
clean["on_time"] == "true",
int(clean["product_quantity"]),
clean["driver_identifier"],
),
)
con.commit()
con.close()
print("Spreadsheet 0 inserted successfully!")
What changed here?
- {k.strip(): v.strip() for k, v in row.items()} creates a new dictionary where every key and value has leading and trailing spaces removed.
- clean["on_time"] == "true" converts the string "true" to Python's True and anything else to False. SQLite stores booleans as 1 or 0.
- int(clean["product_quantity"]) converts the string quantity into an integer so the database stores a number, not text.
Run this cell. You should see Spreadsheet 0 inserted successfully! printed with no errors.
Still seeing a KeyError?
- Make sure the clean = {k.strip(): v.strip() ...} line comes before the cur.execute call. If you still reference row["..."] instead of clean["..."], the whitespace is still there.
- If the database already has partial data from a failed cell run, you need to reset it. Run !git -C /content/forage-walmart-task-4 checkout -- data/shipping_data.db in a new cell, then re-run your insert cell.
Help me fix this KeyError in my insert code
To confirm the data is actually in the database, run a quick row count in a new cell:
# Quick row count check
con = sqlite3.connect(db_path)
count = con.execute('SELECT COUNT(*) FROM shipments').fetchone()[0]
print(f"Rows in database: {count}")
con.close()
You should see a number printed (around 100), confirming that spreadsheet 0's rows are stored in the database.
✔️ Awesome, I've got everything!
Great. Double check you have saved populate.py and confirm it has no leftover print statements from the previous step.
ⓧ I'd like to double check the full code
Your populate.py should contain these sections in order:
- Three imports: csv, sqlite3, os.
- script_dir set with os.path.dirname(os.path.abspath(__file__)).
- Four path variables: db_path, csv0_path, csv1_path, csv2_path.
- Database connection: con = sqlite3.connect(db_path) and cur = con.cursor().
- A with open(csv0_path, newline="") as f: block containing csv.DictReader, the clean dict comprehension with .strip(), and the parameterized cur.execute INSERT.
- con.commit() followed by con.close().
Spreadsheet 0 is loaded. Next up, you will tackle the harder challenge: merging spreadsheets 1 and 2, which each contain only half the information you need.
Merge Spreadsheets 1 and 2
Spreadsheet 0 was the easy one. It had every column the database needed, so you just mapped and inserted. Spreadsheets 1 and 2 are a different story.
Each file only has part of the picture. Spreadsheet 1 has products and on-time status, but no origin or destination. Spreadsheet 2 has origin, destination, and driver info, but no products. You need to join them by shipment_identifier and count product rows to figure out quantities.
In this step, get ready to:
- Build a lookup dictionary from spreadsheet 2 for instant access to location data.
- Group and count products from spreadsheet 1 to determine quantities.
- Print merged rows to verify the join logic before inserting into the database.
Build a lookup dictionary from spreadsheet 2
Spreadsheet 2 has 20 rows, one per shipment. Each row contains the origin_warehouse, destination_store, and driver_identifier for a given shipment_identifier. A Python dictionary lets you look up any shipment's location data instantly by its ID.
- Create a new cell and paste the lookup dictionary code:
# --- Build lookup from spreadsheet 2 ---
shipment_info = {}
with open(csv2_path, newline="") as f:
reader = csv.DictReader(f)
for row in reader:
clean = {k.strip(): v.strip() for k, v in row.items()}
shipment_info[clean["shipment_identifier"]] = {
"origin_warehouse": clean["origin_warehouse"],
"destination_store": clean["destination_store"],
"driver_identifier": clean["driver_identifier"],
}
print(f"Loaded {len(shipment_info)} shipments from spreadsheet 2")
What does this code do?
- shipment_info = {} creates an empty dictionary that will map each shipment ID to its location details.
- The for row in reader loop reads every row from shipping_data_2.csv and strips whitespace (the same technique you used for spreadsheet 0).
- Each shipment's shipment_identifier becomes a dictionary key, and its warehouse, store, and driver become the value. This gives you O(1) lookups later.
- The print at the end is a temporary check to confirm the dictionary was built correctly.
Run this cell. You should see Loaded 20 shipments from spreadsheet 2 printed in the output. That confirms all 20 shipment records from the CSV are now in your dictionary.
Seeing a KeyError or 0 shipments?
- Make sure you ran the imports and file paths cell from Step 1 first. Variables like csv2_path must be defined.
- Check that your clean dictionary comprehension strips both keys and values. A missing .strip() means the key "shipment_identifier " (with trailing space) won't match "shipment_identifier".
Still stuck? Why is my shipment_info dictionary empty or throwing a KeyError?
Group and count products from spreadsheet 1
- Create a new cell and paste the grouping code:
# --- Group and count products from spreadsheet 1 ---
shipment_products = {}
with open(csv1_path, newline="") as f:
reader = csv.DictReader(f)
for row in reader:
clean = {k.strip(): v.strip() for k, v in row.items()}
ship_id = clean["shipment_identifier"]
product = clean["product"]
on_time = clean["on_time"] == "true"
if ship_id not in shipment_products:
shipment_products[ship_id] = {}
if product not in shipment_products[ship_id]:
shipment_products[ship_id][product] = {"quantity": 0, "on_time": on_time}
shipment_products[ship_id][product]["quantity"] += 1
print(f"Grouped products for {len(shipment_products)} shipments")
Run this cell. You should see Grouped products for 20 shipments printed.
Print merged rows to verify the join
What does this code do?
This builds a nested dictionary structure: {shipment_id: {product_name: {"quantity": count, "on_time": bool}}}.
- For each row, it extracts the ship_id and product name.
- If this shipment hasn't been seen before, it creates an empty dictionary for it.
- If this product hasn't been seen for this shipment, it initializes it with a quantity of 0.
- Every time the same (shipment, product) pair appears, the quantity increments by 1. This is how you derive quantity from row counts.
- Create a new cell and paste this verification code:
Print merged rows to verify the join
You now have location data in shipment_info and product data in shipment_products. The final piece is combining them to produce complete rows that match the database schema.
- Add the following code below the shipment_products block (still above con.close()):
# Print a few merged rows to verify
for ship_id, products in list(shipment_products.items())[:2]:
info = shipment_info[ship_id]
for product, details in products.items():
print({"ship_id": ship_id, "product": product, "details": details, "info": info})
What does this code do?
- list(shipment_products.items())[:2] grabs just the first 2 shipments so you don't flood the terminal.
- For each shipment, it looks up the matching location data from shipment_info using the same ship_id key.
- The printed dictionary shows all the fields together: product name, quantity, on-time status, origin warehouse, destination store, and driver. This proves the join works before you insert anything.
Before you run this, what do you expect to see? Each printed dictionary should combine product details (name, quantity, on-time) with location details (origin, destination, driver) for a single shipment-product pair.
Run this cell. You should see printed dictionaries containing fields like ship_id, product, details (with quantity and on_time), and info (with origin_warehouse, destination_store, and driver_identifier). Each row is a complete record ready for the database.
Seeing a KeyError on shipment_info lookup?
- This means a shipment_identifier from spreadsheet 1 has no matching entry in spreadsheet 2. Check that you ran the spreadsheet 2 cell first (the one that builds shipment_info).
- Make sure you are stripping whitespace on both files. A key like "S1 " will not match "S1".
Still stuck? Why is my merged print throwing a KeyError when looking up shipment_info?
✔️ Awesome, I've got everything!
Great. Double check you have saved populate.py and confirm you see the merged dictionaries printed in your terminal.
ⓧ I'd like to double check the full code
Your populate.py should contain these sections in order. Scroll through your file and confirm each one is present:
- Imports (csv, sqlite3, os) and file path setup.
- Database connection (con and cur).
- Insert spreadsheet 0 block with con.commit() at the end.
- Build lookup from spreadsheet 2 (shipment_info dictionary).
- Group and count products from spreadsheet 1 (shipment_products dictionary).
- Print a few merged rows to verify.
- con.close() at the very end.
Your data is joined and verified. Next up, you will insert this merged data into the database and run a final count to confirm everything loaded correctly.
Insert Merged Data and Verify
In the last step, you built two dictionaries that together hold all the information from spreadsheets 1 and 2. shipment_info maps each shipment to its warehouse, store, and driver. shipment_products maps each shipment to its products and counted quantities.
Now it is time to loop through those dictionaries, insert every merged row into the database, and verify the final count to confirm the full pipeline works end-to-end.
In this step, get ready to:
- Insert all merged spreadsheet 1+2 rows into the database.
- Add a verification query that prints the total row count.
- Run the script from scratch to confirm the full pipeline works.
Insert the merged spreadsheet 1+2 data into the database
Your debug print loop served its purpose. Now you will replace it with the real insert logic that writes every merged row into the shipments table.
- Create a new cell and paste the insert loop for the merged data:
# Print a few merged rows to verify
for ship_id, products in list(shipment_products.items())[:2]:
info = shipment_info[ship_id]
for product, details in products.items():
print({"ship_id": ship_id, "product": product, "details": details, "info": info})
con.close()
- Delete that entire block (from the # Print a few merged rows comment down to and including con.close()).
- Replace it with the following insert loop:
# --- Insert merged spreadsheet 1+2 data ---
con = sqlite3.connect(db_path)
cur = con.cursor()
for ship_id, products in shipment_products.items():
info = shipment_info[ship_id]
for product, details in products.items():
cur.execute(
"INSERT INTO shipments (origin_warehouse, destination_store, product, on_time, product_quantity, driver_identifier) VALUES (?, ?, ?, ?, ?, ?)",
(
info["origin_warehouse"],
info["destination_store"],
product,
details["on_time"],
details["quantity"],
info["driver_identifier"],
),
)
con.commit()
con.close()
print("Merged data inserted!")
What does this code do?
This nested loop visits every shipment and every product within that shipment. For each product, it pulls the warehouse and driver data from shipment_info and the quantity from shipment_products.
The ? placeholders keep your INSERT safe from SQL injection by letting SQLite handle value escaping. con.commit() saves the transaction to disk.
🙋♀️ Seeing a KeyError?
If you get a KeyError on a key like origin_warehouse, make sure the spreadsheet 2 reading code above still strips whitespace with .strip() on both keys and values.
help me debug a KeyError in my shipment insert loop
Add a verification query
After inserting all the data, you want proof that it landed in the database. A quick SELECT COUNT(*) query tells you exactly how many rows exist.
- Add a verification query in a new cell to confirm the total row count:
# --- Verify ---
con = sqlite3.connect(db_path)
cur = con.cursor()
cur.execute("SELECT COUNT(*) FROM shipments")
count = cur.fetchone()[0]
print(f"Done! Inserted {count} total shipment records into the database.")
con.close()
What does this code do?
cur.fetchone()[0] grabs the first column of the first result row, which is the count. The f-string prints a human-readable confirmation so you can verify the pipeline at a glance.
con.close() cleanly shuts the database connection when the script finishes.
Run this cell. You should see Merged data inserted! printed with no errors.
Script won't save?
Make sure you do not have a syntax error. Check that the con.close() line sits at the top indentation level (no extra spaces before it).
help me fix a syntax issue in my populate.py script
Run the final script end-to-end
Your script already inserted spreadsheet 0 data during earlier test runs. Running it again would create duplicate rows. You need to reset the database to its original empty state first.
- Reset the database to its original empty state by running this in a new cell:
!git -C /content/forage-walmart-task-4 checkout -- data/shipping_data.db
What does this command do?
git checkout -- restores a single file to the version saved in your last Git commit. This gives you the empty database schema without any inserted rows, so your script can populate it from scratch.
Before you run the script, think about what you expect to see. The script processes all rows from spreadsheet 0 and all merged product rows from spreadsheets 1 and 2. What total count do you think it will print?
- Now run all your insert cells in order (spreadsheet 0, then the merged insert), followed by the verification cell.
You should see a message like:
You should see a message like:
Done! Inserted 157 total shipment records into the database.
What should I see?
Your exact number may vary slightly depending on the CSV row counts, but the key confirmation is that the script runs without errors and prints a total that combines all three spreadsheets. If you see any count printed, your end-to-end pipeline is working.
🙋♀️ Seeing duplicate data or a much higher count?
You likely forgot to reset the database before re-running. Run git checkout -- data/shipping_data.db again, then run python populate.py once more.
help me figure out why my row count is wrong
✔️ Awesome, I've got everything!
Great. Double check you have saved populate.py and that your terminal printed a total row count.
ⓧ I'd like to double check the full code
Your populate.py should contain these sections in order. Scroll through and confirm each one is present:
- Imports (csv, sqlite3, os) and file path setup using os.path.join.
- Database connection with sqlite3.connect(db_path).
- Insert spreadsheet 0 block: opens csv0_path, strips whitespace, inserts each row, then con.commit().
- Build lookup from spreadsheet 2: reads csv2_path into shipment_info dictionary.
- Group and count products from spreadsheet 1: reads csv1_path into shipment_products dictionary.
- Insert merged spreadsheet 1+2 data: nested loop through shipment_products and shipment_info, then con.commit().
- Verify block: SELECT COUNT(*) query, print the count, then con.close().
Secret mission
Add a Shipment Statistics Summary
Your script loads data silently. A professional pipeline reports what it did. Add SQL aggregate queries that print a formatted summary showing total shipments, on-time rate, top product, and warehouse count.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely in Google Colab, so there are no ongoing costs. Decide whether to keep your resources, pause them to come back later, or delete them entirely.
Resources you used:
- Google Colab notebook (populate.ipynb).
- Cloned repository in Colab's /content/forage-walmart-task-4/ directory.
- Populated data in shipping_data.db (rows inserted during this project).
Keep everything running
No action needed. Choose this if you plan to continue experimenting with the notebook or want to keep your populated database.
- Your notebook stays saved in your Google Drive under Colab Notebooks.
- Note that the cloned repo in /content/ is wiped when the Colab runtime disconnects. You can re-clone it by re-running the first cell next time.
Pause - I'll come back to this later
Colab automatically disconnects after a period of inactivity. Your notebook is saved, but the runtime files (the cloned repo) are deleted.
- No action needed. When you reopen the notebook, re-run the git clone cell and the imports/paths cell to restore your environment.
Delete - I don't want to use this again
Remove the notebook and any trace of this project from your Google account.
- Open Google Drive and navigate to the Colab Notebooks folder.
- Right-click populate.ipynb and select Move to trash.
- If you forked the GitHub repository and no longer need it, go to your fork at github.com, click Settings, scroll to the bottom, and click Delete this repository.
Nice Work!
Nice Work!
You just built a complete data pipeline from scratch. Your Python script reads three messy spreadsheets, cleans and merges the data, and loads it all into a queryable SQLite database.
You've learned how to:
- Read and parse CSV files with different schemas using Python's built-in csv module.
- Join two incomplete datasets into a unified format using Python dictionaries as lookup tables.
- Load transformed data into a SQLite database using parameterized queries with sqlite3.
- Secret Mission: Built a verification summary that reports shipment statistics using SQL aggregate queries.
Ready to quiz yourself?