In partnership with

We have covered the basics (variables, loops, functions), then pandas (loading, cleaning, exploring data). Today we are adding the final piece — visualisations.

You can stare at a table of numbers for five minutes and still miss the story. A good chart can show it in five seconds.

We are continuing with the same Cafe Sales dataset from Part 2. If you missed it, download it here: https://www.kaggle.com/datasets/ahmedmohamed2003/cafe-sales-dirty-data-for-cleaning-training

And if you want to review previous parts, you can find them here → link

Before we proceed - a small ad. Your clicks on the ads help to cover newsletter hosting fees. Thank you!

You've seen the AI demos. Viktor does it without you watching.

The AI tool you tried last quarter waited for a prompt, hallucinated a number, then asked if you'd like a summary.

Viktor opened a PR at 2am, rebased it against main, ran your test suite, and posted a note in #eng: "Two flaky tests in payments service, both pre-existing. Recommended merging after fixing them." Then drafted the customer reply for the support ticket the bug created.

That's 619K autonomous actions per day across 20,000+ teams. Not chat replies. Real work shipped to GitHub, Stripe, Linear, Notion, and 3,000+ other tools, from inside Slack and Microsoft Teams.

You don't supervise him any more than you supervise a senior engineer.

SOC 2 certified. Your data never trains models.

"It's what you probably originally thought AI was going to be when you first heard of it in sci-fi movies." Tyler, CEO.

The libraries

We are using two libraries today:

Matplotlib — the foundation of Python visualisation. Almost every chart in Python is built on matplotlib under the hood. The charts are not very pretty, but very customisable.

Seaborn — built on top of matplotlib, but with much nicer default styles and less code. This is what most analysts use.

# Install if needed (pre-installed in Google Colab)
# !pip install matplotlib seaborn

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# Set the visual style
sns.set_theme(style='whitegrid')

sns.set_theme() makes all your charts look clean and professional. Always add this at the top.

Step 1 — Load and clean your data

We are starting from where we left off in Part 2. Run this to get your clean dataset ready.

from google.colab import files
uploaded = files.upload()

df = pd.read_csv('dirty_cafe_sales.csv')

# Clean — same steps as Part 2
df = df.replace(['UNKNOWN', 'ERROR'], pd.NA)
df['Price Per Unit'] = pd.to_numeric(df['Price Per Unit'], errors='coerce')
df['Quantity'] = pd.to_numeric(df['Quantity'], errors='coerce')
df['Transaction Date'] = pd.to_datetime( df['Transaction Date'], errors='coerce' )
df = df.dropna(subset=['Item', 'Price Per Unit', 'Quantity'])
df['Total Sales'] = df['Price Per Unit'] * df['Quantity']

Step 2 — Bar chart: top selling items

Bar charts are the most common chart in data analytics. Clear, simple, everyone understands them.

At my last workplace, we used bar charts for everything, while line charts were nearly banned. Don’t ask why.

# Calculate total sales by item
item_sales = df.groupby('Item')['Total Sales']
    .sum().sort_values(ascending=False).head(10)

# Plot
plt.figure(figsize=(10, 6))

item_sales.plot(
    kind='bar', color='steelblue', edgecolor='white')

plt.title('Top 10 Items by Total Sales', fontsize=14)
plt.xlabel('Item', fontsize=11)
plt.ylabel('Total Sales', fontsize=11)
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.show()

plt.tight_layout() prevents labels from getting cut off. Always add it before plt.show().

Step 3 — Horizontal bar chart: payment methods

When your category labels are long, a horizontal bar chart is easier to read than a vertical one.

payment_sales = df.groupby('Payment Method')['Total Sales'].sum().sort_values()

plt.figure(figsize=(8, 5))
payment_sales.plot(kind='barh', color='coral', edgecolor='white')
plt.title('Total Sales by Payment Method', fontsize=14)
plt.xlabel('Total Sales', fontsize=11)
plt.tight_layout()
plt.show()

Note: Payment Method has some nulls so not all rows will appear — this is expected from our cleaning step.

Step 4 — Line chart: sales over time

Line charts show trends. If your data has a date column, this is usually the first chart you build.

# Group by date
daily_sales = ( 
  df.groupby('Transaction Date')['Total Sales'] 
    .sum() 
    .sort_index() 
)

plt.figure(figsize=(12, 5))
daily_sales.plot(kind='line', color='steelblue', linewidth=1.5)
plt.title('Daily Sales Over Time', fontsize=14)
plt.xlabel('Date', fontsize=11)
plt.ylabel('Total Sales', fontsize=11)
plt.tight_layout()
plt.show()

Questions to ask:

  • Are sales increasing or decreasing over time?

  • Are there unusual spikes?

  • Do some periods perform much better than others?

Step 5 — Histogram: distribution of transaction values

Histograms show you the distribution of a numeric column — where most values sit, whether there are outliers.

plt.figure(figsize=(9, 5))
df['Total Sales'].hist(bins=30, color='mediumseagreen', edgecolor='white')
plt.title('Distribution of Transaction Values', fontsize=14)
plt.xlabel('Total Sales', fontsize=11)
plt.ylabel('Number of Transactions', fontsize=11)
plt.tight_layout()
plt.show()

What are you looking for?

  • Are most transactions small, with a few very large purchases?

  • Is the distribution roughly balanced?

  • Are there suspicious outliers?

These are the types of questions pricing, operations, and fraud teams investigate regularly.

Step 6 — Seaborn boxplot: comparing distributions

A boxplot shows you the spread of values across categories — median, range, and outliers all in one chart.

plt.figure(figsize=(10, 6))
sns.boxplot( data=df, x='Item', y='Total Sales')
plt.title('Total Sales Distribution by Item', fontsize=14)
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.show()

This chart tells a different story from the revenue chart.

Two items might generate similar revenue overall, but one may have highly variable transaction values while the other sells consistently.

Step 7 — Save your charts

plt.tight_layout()
# Save the last chart as a PNG file
plt.savefig('sales_by_item.png', dpi=150, bbox_inches='tight')
plt.show()

Add this before plt.show() to save any chart. dpi=150 gives you a high enough resolution for presentations and portfolio writeups.

What you just built

You now know how to create:

  • Bar charts

  • Horizontal bar charts

  • Line charts

  • Histograms

  • Boxplots

These five chart types cover the vast majority of visualisations used in day-to-day analytics work.

How to turn this into a portfolio project

You now have all three parts of a complete Python analysis:

  • Part 1 — Python basics

  • Part 2 — Data loading and cleaning with pandas

  • Part 3 — Visualisations

Put them together into one notebook, add markdown cells explaining your findings, and you have a portfolio project. Upload it to GitHub and link it on your CV and Linkedin About section.

One more thing — is the Google Data Analytics Certificate worth it?

I get this question constantly. So this week I recorded a full YouTube video giving my honest answer — what the certificate actually teaches, who it is genuinely useful for, and where it falls short.

If you are considering it or already doing it, this video is for you.

Watch it here → link

Keep pushing 💪,

Karina

Just starting with Python? Wondering if programming is for you?

Master key data analysis tasks like cleaning, filtering, pivot and grouping data using Pandas, and learn how to present your insights visually with Matplotlib with ‘Data Analysis with Python’ masterclass.

Already know the basics and want something more hands-on?

You'll work through a real business problem, complete a portfolio-ready project, and practise the kind of analysis employers expect from junior analysts.

👉 Start with the Masterclass if you're a complete beginner.

👉 Choose the Python Challenge if you're comfortable with the fundamentals and want to apply them to a real project.

Data Analyst & Data Scientist

Keep Reading