Optional: Working with Databases#
Storing and querying data in SQL databases.
Learning Objectives#
Understand when to use databases vs files
Create and query SQLite databases
Use pandas with SQL
Design simple database schemas
import sqlite3
import pandas as pd
import numpy as np
When to Use Databases#
Use Case |
Files |
Database |
|---|---|---|
Small datasets (<10K rows) |
✓ |
|
Large datasets |
✓ |
|
Multiple users accessing data |
✓ |
|
Complex queries |
✓ |
|
Data integrity important |
✓ |
|
One-time analysis |
✓ |
# Create an SQLite database
conn = sqlite3.connect('experiments.db')
cursor = conn.cursor()
# Create tables
cursor.execute('''
CREATE TABLE IF NOT EXISTS experiments (
id INTEGER PRIMARY KEY,
date TEXT,
temperature REAL,
pressure REAL,
catalyst TEXT,
conversion REAL
)
''')
conn.commit()
print("Database created!")
Database created!
# Insert data
experiments = [
('2024-01-15', 350, 5.0, 'Pt/Al2O3', 0.72),
('2024-01-16', 400, 5.0, 'Pt/Al2O3', 0.85),
('2024-01-17', 350, 10.0, 'Pt/Al2O3', 0.78),
('2024-01-18', 400, 10.0, 'Pd/Al2O3', 0.82),
('2024-01-19', 450, 5.0, 'Pd/Al2O3', 0.91),
]
cursor.executemany('''
INSERT INTO experiments (date, temperature, pressure, catalyst, conversion)
VALUES (?, ?, ?, ?, ?)
''', experiments)
conn.commit()
print(f"Inserted {len(experiments)} records")
Inserted 5 records
# Query with pandas
df = pd.read_sql_query('SELECT * FROM experiments', conn)
df
| id | date | temperature | pressure | catalyst | conversion | |
|---|---|---|---|---|---|---|
| 0 | 1 | 2024-01-15 | 350.0 | 5.0 | Pt/Al2O3 | 0.72 |
| 1 | 2 | 2024-01-16 | 400.0 | 5.0 | Pt/Al2O3 | 0.85 |
| 2 | 3 | 2024-01-17 | 350.0 | 10.0 | Pt/Al2O3 | 0.78 |
| 3 | 4 | 2024-01-18 | 400.0 | 10.0 | Pd/Al2O3 | 0.82 |
| 4 | 5 | 2024-01-19 | 450.0 | 5.0 | Pd/Al2O3 | 0.91 |
# Filtered queries
high_conversion = pd.read_sql_query('''
SELECT * FROM experiments
WHERE conversion > 0.8
ORDER BY conversion DESC
''', conn)
print("High conversion experiments:")
high_conversion
High conversion experiments:
| id | date | temperature | pressure | catalyst | conversion | |
|---|---|---|---|---|---|---|
| 0 | 5 | 2024-01-19 | 450.0 | 5.0 | Pd/Al2O3 | 0.91 |
| 1 | 2 | 2024-01-16 | 400.0 | 5.0 | Pt/Al2O3 | 0.85 |
| 2 | 4 | 2024-01-18 | 400.0 | 10.0 | Pd/Al2O3 | 0.82 |
# Aggregation
summary = pd.read_sql_query('''
SELECT catalyst,
COUNT(*) as n_experiments,
AVG(conversion) as avg_conversion,
MAX(conversion) as max_conversion
FROM experiments
GROUP BY catalyst
''', conn)
print("Summary by catalyst:")
summary
Summary by catalyst:
| catalyst | n_experiments | avg_conversion | max_conversion | |
|---|---|---|---|---|
| 0 | Pd/Al2O3 | 2 | 0.865000 | 0.91 |
| 1 | Pt/Al2O3 | 3 | 0.783333 | 0.85 |
# Save DataFrame to database
new_data = pd.DataFrame({
'date': ['2024-01-20', '2024-01-21'],
'temperature': [375, 425],
'pressure': [7.5, 7.5],
'catalyst': ['Pt/Al2O3', 'Pt/Al2O3'],
'conversion': [0.79, 0.88]
})
new_data.to_sql('experiments', conn, if_exists='append', index=False)
print("Data appended!")
Data appended!
# Clean up
conn.close()
import os
os.remove('experiments.db')
print("Database cleaned up")
Database cleaned up
%pip install -q jupyterquiz
from jupyterquiz import display_quiz
display_quiz("https://raw.githubusercontent.com/jkitchin/s26-06642/main/dsmles/optional/quizzes/databases-quiz.json")
Note: you may need to restart the kernel to use updated packages.
Summary#
SQLite is a lightweight database for local use
Use
pd.read_sql_query()to load data into pandasUse
df.to_sql()to save DataFrames to databaseSQL queries enable complex filtering and aggregation
For production use, consider PostgreSQL or MySQL.