Mathew K Analytics

Lesson 58 · Mastering Pandas

How to Create an Interactive KPI Dashboard Using Python and Pandas

Welcome to this intermediate-beginner lesson on building KPI dashboards in Python with Pandas. Key Performance Indicators (KPIs) are vital numbers that help…

⬇ Download notebookOpen in Colab ↗

What you'll learn

Data

No separate download needed — the notebook creates or downloads everything it uses.

📓 Full notebook

Download .ipynb

Building a KPI Dashboard with Pandas#

Welcome to this intermediate-beginner lesson on building KPI dashboards in Python with Pandas. Key Performance Indicators (KPIs) are vital numbers that help organizations measure progress. In this lesson, we will build simple but powerful dashboard metrics using Pandas.

We will use the famous Titanic dataset to explore, clean, analyze, and visualize data. Lets get started!

import warnings
import numpy as np
np.random.seed(42)
warnings.filterwarnings("ignore")  # Suppress warnings for a cleaner lesson
# Data setup (Titanic Dataset)
import pandas as pd
url = 'https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv'
df = pd.read_csv(url)
print(df.shape)
print(df.head(3))
(891, 12)
   PassengerId  Survived  Pclass  \
0            1         0       3   
1            2         1       1   
2            3         1       3   

                                                Name     Sex   Age  SibSp  \
0                            Braund, Mr. Owen Harris    male  22.0      1   
1  Cumings, Mrs. John Bradley (Florence Briggs Th...  female  38.0      1   
2                             Heikkinen, Miss. Laina  female  26.0      0   

   Parch            Ticket     Fare Cabin Embarked  
0      0         A/5 21171   7.2500   NaN        S  
1      0          PC 17599  71.2833   C85        C  
2      0  STON/O2. 3101282   7.9250   NaN        S  

What is a DataFrame?#

Pandas DataFrame is like a table of data with rows and columns. It holds our dataset, so we can select, filter, summarize, and plot with ease.

Lets check out some basic info about our Titanic data.

# Preview key info and columns
print(df.info())
print(df.columns)
print(df.describe())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
None
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
       'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
      dtype='object')
       PassengerId    Survived      Pclass         Age       SibSp  \
count   891.000000  891.000000  891.000000  714.000000  891.000000   
mean    446.000000    0.383838    2.308642   29.699118    0.523008   
std     257.353842    0.486592    0.836071   14.526497    1.102743   
min       1.000000    0.000000    1.000000    0.420000    0.000000   
25%     223.500000    0.000000    2.000000   20.125000    0.000000   
50%     446.000000    0.000000    3.000000   28.000000    0.000000   
75%     668.500000    1.000000    3.000000   38.000000    1.000000   
max     891.000000    1.000000    3.000000   80.000000    8.000000   

            Parch        Fare  
count  891.000000  891.000000  
mean     0.381594   32.204208  
std      0.806057   49.693429  
min      0.000000    0.000000  
25%      0.000000    7.910400  
50%      0.000000   14.454200  
75%      0.000000   31.000000  
max      6.000000  512.329200  

Data Cleaning Basics#

Real-world data often has missing values or inconsistent formats. We want our KPIs to be based on clean data. First, lets find and handle missing values.

# Check for missing values
print(df.isnull().sum())

# Fill missing Age values with the median age
df['Age'] = df['Age'].fillna(df['Age'].median())

# Remove rows with missing Embarked values
df = df.dropna(subset=['Embarked'])

print('After cleaning:')
print(df.isnull().sum())
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64
After cleaning:
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age              0
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         0
dtype: int64
# Convert data types for categories
df['Pclass'] = df['Pclass'].astype('category')
df['Sex'] = df['Sex'].astype('category')
df['Embarked'] = df['Embarked'].astype('category')

Creating KPI Columns#

KPIs should be clear and actionable. Lets create a few columns that we will use for our dashboard metrics.

# Create 'IsChild' KPI: Age under 16
df['IsChild'] = df['Age'] < 16

# Create 'FamilySize' KPI: count siblings, spouses, parents, children
df['FamilySize'] = df['SibSp'] + df['Parch'] + 1
# Filtering examples: Women, Children, Third class
women = df[df['Sex'] == 'female']
children = df[df['IsChild']]
third_class = df[df['Pclass'] == 3]
print(f"Number of women: {women.shape[0]}")
print(f"Number of children: {children.shape[0]}")
print(f"Number in third class: {third_class.shape[0]}")
Number of women: 312
Number of children: 83
Number in third class: 491

Aggregating KPIs: Survival Rates#

KPIs often summarize data, like calculating rates per group. Lets check the overall survival rate and break it down by class and sex.

# Overall survival rate
survival_rate = df['Survived'].mean()
print(f"Overall survival rate: {survival_rate:.2%}")

# Survival by class
class_rates = df.groupby('Pclass')['Survived'].mean()
print("Survival rate by class:")
print(class_rates)

# Survival by sex
sex_rates = df.groupby('Sex')['Survived'].mean()
print("Survival rate by sex:")
print(sex_rates)
Overall survival rate: 38.25%
Survival rate by class:
Pclass
1    0.626168
2    0.472826
3    0.242363
Name: Survived, dtype: float64
Survival rate by sex:
Sex
female    0.740385
male      0.188908
Name: Survived, dtype: float64

Advanced Grouping: Multi-dimensional KPIs#

Pandas lets us group by several columns at once. This is helpful for 'KPI tables' with multiple categories. Lets see survival rates by both class and sex.

# Group by class AND sex for a KPI 'matrix'
pivot = df.pivot_table('Survived', index='Pclass', columns='Sex', aggfunc='mean')
print(pivot)
Sex       female      male
Pclass                    
1       0.967391  0.368852
2       0.921053  0.157407
3       0.500000  0.135447
# KPI: Average Fare by Embarked point and Class
kpi_fare = df.groupby(['Embarked', 'Pclass'])['Fare'].mean().unstack()
print(kpi_fare)
Pclass             1          2          3
Embarked                                  
C         104.718529  25.358335  11.214083
Q          90.000000  12.350000  11.183393
S          70.364862  20.327439  14.644083

Adding Time-Based KPIs#

Dashboards often track metrics over time. Although Titanic does not have a proper timestamp, lets use the Ticket column's first character as a 'proxy' for time to create a demonstration.

# Create a 'FakeTime' column from ticket prefix
df['FakeTime'] = df['Ticket'].astype(str).str[0]
# Time-based KPI: mean age by FakeTime
age_time = df.groupby('FakeTime')['Age'].mean()
print(age_time)
FakeTime
1    35.322361
2    27.875683
3    26.666113
4    31.300000
5    32.166667
6    33.500000
7    27.777778
8    26.500000
9    28.000000
A    29.086207
C    26.106383
F    34.142857
L    32.250000
P    34.523077
S    27.446154
W    33.769231
Name: Age, dtype: float64
# Visualize key KPIs with plots
import matplotlib.pyplot as plt
plt.figure(figsize=(7,5))
df.groupby('Pclass')['Survived'].mean().plot(kind='bar', color=['#1976D2', '#388E3C', '#FBC02D'])
plt.title('Survival Rate by Class')
plt.ylabel('Survival Rate')
plt.ylim(0, 1)
plt.show()
No description has been provided for this image
# Mini-project: Build a KPI summary dashboard
kpi_dashboard = pd.DataFrame({
    'KPI': ['Total Passengers', 'Children', 'Women', 'Mean Fare', 'Overall Survival Rate'],
    'Value': [
        df.shape[0],
        df['IsChild'].sum(),
        (df['Sex'] == 'female').sum(),
        df['Fare'].mean(),
        df['Survived'].mean(),
    ]
})
print(kpi_dashboard)
                     KPI       Value
0       Total Passengers  889.000000
1               Children   83.000000
2                  Women  312.000000
3              Mean Fare   32.096681
4  Overall Survival Rate    0.382452
# Challenge: Add an interactive filter
embarked_choice = input("Type a port of embarkation (C, Q, S): ")
filtered = df[df['Embarked'] == embarked_choice]
print(f"Number of passengers who boarded at {embarked_choice}: {filtered.shape[0]}")
print(f"Survival rate at {embarked_choice}: {filtered['Survived'].mean():.2%}")
Number of passengers who boarded at S: 644
Survival rate at S: 33.70%
# Dashboard best practices: handle missing data gracefully
def safe_survival_rate(df):
    if df.empty:
        return float('nan')
    return df['Survived'].mean()

silly_port = input("Try a non-existent port code: ")
filtered2 = df[df['Embarked'] == silly_port]
print(f"Rows: {filtered2.shape[0]}, Survival: {safe_survival_rate(filtered2)}")
Rows: 0, Survival: nan

Recap: What We Learned#

  • Loaded and explored Titanic data
  • Cleaned and converted columns for analysis
  • Created custom KPIs
  • Grouped and summarized key business metrics
  • Built and visualized a KPI dashboard
  • Added interactivity and handled missing data safely

Try building a similar dashboard with your own data or datasets from public sources. Practicing with new data is how you will master these techniques!

Enjoyed this Lesson?#

If you found this useful, please like the video and subscribe to our channel. Comment with your KPI dashboard ideas or questionswe love hearing from you! Happy coding and see you soon!

Found this useful?

All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.