Week 2: How We Work with Data in Python
With your neighbor (3 min): what does each snippet print — before running it?
Answers:
Today’s Session
Follow along: Open the companion notebook and run code as we work through each concept.
Participate: We’ll pause throughout for group discussions and hands-on activities — come ready to think out loud with your neighbors!
Your manager gives you customer data and asks for a report by Friday that:
How would you approach this before this class?
And — what breaks at step 5 when new data arrives next month?
⏳ You have 2–3 minutes — chat with a neighbor!
❌ Traditional Workflow Problems
Excel Analysis
↓
Screenshot Charts
↓
Word Document
↓
Email to Boss
↓
"Can you update this?"
↓
Start over! 😱
✅ Jupyter Notebook Solution
Data + Code + Narrative
↓
Single Document
↓
Export & Share
↓
"Update with new data?"
↓
Re-run notebook! 🎉
Bottom line: Notebooks let you explore, document, and communicate all in one place. Change one cell — the entire report updates.
From your reading: Notebooks combine two cell types for complete analysis documentation
📝 Markdown Cells
Like the narrative in a business report
🐍 Code Cells
Like the calculations in a spreadsheet
The Magic: These work together to create professional, reproducible analysis reports!
A single code cell holds your logic and its output — no copy/paste into a slide deck.
# Quarterly revenue analysis — code and result live together in one cell
revenue = {"Q1": 125_000, "Q2": 98_000, "Q3": 142_000, "Q4": 110_000}
annual = sum(revenue.values())
best_quarter = max(revenue, key=revenue.get)
print(f"Annual revenue: ${annual:,.0f}")
print(f"Quarterly avg: ${annual / 4:,.0f}")
print(f"Best quarter: {best_quarter} (${revenue[best_quarter]:,.0f})")Annual revenue: $475,000
Quarterly avg: $118,750
Best quarter: Q3 ($142,000)
✏️ Your Turn
In the companion notebook, find the “Try It” cell for this section. Write code that:
The 3-cell pattern: context → analysis → interpretation
📝 Markdown Cell — Before
Business Question: Which subscription plan is most popular?
We’ll look at the distribution of customers across plan tiers to identify where to focus retention efforts.
Basic : 820 customers (66%) ████████████████████
Premium : 310 customers (25%) ███████
Enterprise : 120 customers (10%) ███
📝 Markdown Cell — After
Finding: Basic plan dominates at 66% of customers. Premium (25%) is the primary upsell opportunity — targeted Basic → Premium campaigns could meaningfully improve revenue.
Your notebook has three different readers — organization is what lets one document serve all three.
👔 Stakeholders
They need the business story:
Most will never read a line of your code.
🔍 Technical Reviewers
They need your reasoning:
Your code shows what. Your writing shows why.
🔮 Future You
Six months from now:
You will not remember. Write it down.
📂 Open both examples now — we’ll review them next
Both examples: Project notebook · Homework notebook
With your neighbor (5 min) — skim both and discuss:
What works? Do they feel well organized? Are they easy to follow? What stands out as particularly clear or helpful?
What’s missing? What would you add or change to make either one clearer?
Most of what you just called out probably lands somewhere on this list.
📝 Structure — tells the story
✍️ Craft — makes it usable
customer_churn_2026.ipynbImportant
“Structure your notebook like a story — introduce the goal, describe your approach, show the results, and summarize your findings.”
The test: could a stakeholder, a reviewer, and future-you each get what they need — without you in the room to explain it?
🚨 The #1 Problem: Execution order ≠ cell order — output can lie
The number in brackets [N] shows when each cell last ran, not its position:
🔴 Out-of-order (untrustworthy)
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[8], line 1 ----> 1 print(f"Hello {my_name}!") NameError: name 'my_name' is not defined
Pro Tip:
Always restart the kernel and run all cells before sharing your notebook. This ensures that your code runs in the correct order and that all outputs are reproducible.
Open floor for any questions about Jupyter notebooks:
Let’s make sure everyone feels confident with notebooks before moving to data structures!
Last week, we worked with individual data types like:
int for numbersfloat for decimalsstr for textBut in real-world analyses, we usually need to work with collections of values.
Important
This is where data structures come in. Data structures help us organize values.
Python’s built-in structures are designed for the work data analysis actually does:
✅ What They Give You
The Question
Which Python structure fits each business need?
Python gives us four powerful (built-in) tools to organize business data:
| Structure | Ordered? | Mutable? | Best For | Business Example |
|---|---|---|---|---|
| List | ✅ | ✅ | Ordered sequences | Daily sales figures, customer queue |
| Tuple | ✅ | ❌ | Fixed, protected data | Store coordinates, product dimensions |
| Set | ❌ | ✅ | Unique values only | Email subscribers, product categories |
| Dictionary | ❌ | ✅ | Lookups & labeled data | Customer profiles, product catalog |
Tip
The Goal: Match your data’s behavior to the right structure
Choosing the right one makes your code:
For example…
📈 Goal: You’re storing daily sales figures, in order.
[] brackets for creationImportant
✅ A list lets you store sequences of items and modify them easily.
📌 Use when order matters and you’ll be changing the contents.
A few basic things you can do — the readings and lab will go deeper:
Get an item by position:
2105
Append a new item to the end:
[1842, 2105, 1956, 2341, 890, 3102]
Change an existing item:
In your notebook, start with this exact list:
Then:
89 to 128✅ Check your output
196
[182, 205, 196, 234, 128, 310]
📍 Goal: You’re storing a store location that should never change.
() and contains values in sequenceImportant
✅ A tuple protects data from being changed accidentally.
📌 Use when data is fixed and position matters.
Tuples support reading but not writing:
Get items by position:
39.1031
-84.512
Try to change a value — tuples won’t allow it:
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[16], line 2 1 store_location = (39.1031, -84.5120) ----> 2 store_location[0] = 40.0 TypeError: 'tuple' object does not support item assignment
Important
Key Insight: The error is intentional — tuples protect your data from accidental changes.
In your notebook, start with this exact tuple:
Then:
lat and lon, then print both40.0. What happens?✅ Check your output
39.2734 -84.4569 … -84.4569 … then:
TypeError: 'tuple' object does not support item assignment
📧 Goal: You’re collecting unique customer email addresses, no duplicates allowed.
{} brackets but NO key-value pairs (just values)Important
✅ A set ensures all items are unique and provides fast membership testing.
📌 Use when you need to eliminate duplicates or check “is this item in the collection?”
Sets don’t support indexing — but they excel at membership testing and deduplication:
Check if an item exists:
True
False
Add a new item:
In your notebook, start with this exact set — note the repeats:
Then:
len(categories). How many survived?"bakery" in the set? Is "frozen"?"frozen" to the setsorted(categories)✅ Check your output
3 … True False … ['bakery', 'dairy', 'frozen', 'produce']
Use sorted() — a set has no order, so printing it raw varies run to run!
🔎 Goal: You need to look up a product price by name.
dict){}Important
✅ A dictionary allows fast key-based lookup.
📌 Use when you need to map one thing (e.g. product name) to another (e.g. price).
Dictionaries let you look up, add, and update by key:
Get a value by key:
Add a new key-value pair:
{'organic milk': 4.99, 'whole grain bread': 3.29, 'eggs': 2.89}
Update an existing value:
In your notebook, start with this exact dictionary:
Then:
"whole grain bread""cold brew coffee" at 8.992.79✅ Check your output
3.29, then all four items with bread at 2.79 and coffee added at the end.
When choosing a data structure, ask yourself:
Important
Key Insight: The right structure makes your analysis faster, clearer, and more maintainable!
Scenario: Your fraud detection system receives 50,000 transaction IDs per hour. You need to instantly answer: “Have we seen this transaction ID before?”
Vote — which structure would you use?
🅐 List — simple and familiar
🅑 Set — fast membership testing, no duplicates
🅒 Dictionary — key-value lookup by ID
Important
Answer: Set — id in seen_ids is nearly instant regardless of size. A List checks every element one-by-one — fast for 10 items, unusably slow for 50,000.
You’re a data analyst at different companies. Choose the best data structure:
Scenario 1: Social Media Startup 📱 Track trending hashtags from user posts — each hashtag should only appear once, regardless of how many times users post it.
Scenario 2: E-commerce Platform 🛒 Track daily website traffic for 30 days for trend analysis and allow quick lookup of any specific date’s traffic by date.
(Hint: more than one structure could work — be ready to defend your choice!)
Scenario 3: Restaurant Chain 🍕 Store the GPS coordinates of your flagship restaurant. This data will never change and is critical for delivery mapping software.
Scenario 4: University System 🎓 Build a student lookup system where professors can quickly find a student’s information (name, major, GPA) using their student ID number.
🤔 Work with a partner (3 min) — then class vote on Scenario 2!
Choosing the right structure makes your code:
You’ll explore these structures more in depth this week and you’ll get practice:
Tip
Python’s true power comes from its ecosystem of libraries that extend its core functionality
If you needed to calculate the correlation between two variables (x and y)
would you rather…
🛠️ Option 1: Build It Yourself
correlation = 0.9861297973047767
Important
✅ Packages like numpy help us reuse reliable, optimized code
📌 They save time, reduce bugs, and make your code easier to read
Standard Library
– comes with Python (math, datetime)
Third-Party Libraries
numpy, pandas, seaborn)Small difference in accessing these libraries
math, datetime)numpy, pandas, seaborn)Standard Library
osmathitertoolsfunctoolsrandompickledatetimeThird-Party Library
numpypandasmatplotlibseabornscikit-learnNothing to install — random ships with Python.
Scenario: simulate 10 daily sales figures between $3,000 and $8,500.
[5121, 5381, 4521, 8341, 4888, 8457, 4205, 4844, 8250, 4534]
Now use your list skills on the result:
sum()✅ Check your output
Day 1 → 5121 · Day 3 → 4521 · Total → 58542
Two stores this time — and a question random alone can’t answer.
Store A: [5121, 5381, 4521, 8341, 4888, 8457, 4205, 4844, 8250, 4534]
Store B: [4066, 3580, 7352, 4752, 5413, 3245, 6535, 4034, 7984, 3118]
Now bring in a third-party library:
import numpy as np (note np is called an alias)np.mean())np.corrcoef(store_a, store_b)[0, 1]✅ Check your output
Store A mean → 5854.2 · Store B mean → 5007.9 · correlation → 0.026
Essentially zero — we generated the two stores independently, so there’s no relationship to find. numpy gave us the number; you supplied the interpretation.
This one you have to install first — completejourney_py holds the retail data we’ll use all semester.
Then load the data:
['campaign_descriptions', 'campaigns', 'coupon_redemptions', 'coupons', 'demographics', 'products', 'promotions', 'transactions']
1,469,307 rows × 11 columns
| household_id | product_id | quantity | sales_value | |
|---|---|---|---|---|
| 0 | 900 | 1095275 | 1 | 0.50 |
| 1 | 900 | 9878513 | 1 | 0.99 |
| 2 | 1228 | 1041453 | 1 | 1.43 |
📖 Want to explore?
Dataset descriptions and examples: cunningjames.github.io/completejourney_py
Hands-on practice with…
Important
Be sure to read the chapter readings before Thursday’s lab! And bring your questions!
Open floor for any questions regarding…
BANA 4080 | Week 2