Logo OnlineCBT
PYTHON Tutorial
PYTHON · LESSON 59

Data Analysis with NumPy and pandas

Clean, aggregate and inspect tabular data.

Level: Beginner to Advanced
Duration: ~60 Mins Deep-Dive
Updated: 26 Jul 2026

Lesson 59: Data Analysis with NumPy and pandas

1. Introduction to High-Performance Data Computing

Welcome to Module 11 of our Python Mastery Series: Scientific Computing, Data Science and Machine Learning! Over the previous 58 lessons, we have constructed complex object-oriented software architectures, database storage layers, web automation scrapers, and RESTful microservices.

In modern enterprise software engineering, applications ingest vast volumes of numerical metrics—financial trading histories, IoT sensor telemetries, user behavioral analytics, and system audit logs. Processing millions of row records using standard Python for loops and native list data structures introduces severe performance bottlenecks due to dynamic type-checking overhead and fragmented object memory pointers.

To solve this performance challenge and enable lightning-fast numerical and tabular data processing, the global Python data ecosystem relies on two foundational libraries:

  • NumPy (Numerical Python): The core library for scientific computing, providing high-performance, contiguous C-aligned N-dimensional array objects (np.ndarray) and vectorized mathematical operations.
  • pandas (Python Data Analysis Library): Built on top of NumPy, providing rich tabular data structures—Series (1D) and DataFrames (2D)—for data manipulation, filtering, aggregation, missing data alignment, and file I/O operations.

In this lesson, we will master contiguous memory computing via NumPy arrays, vectorized arithmetic, broadcasting rules, tabular manipulation using pandas DataFrames, data cleaning (`dropna()`, `fillna()`), advanced indexing (`loc` vs `iloc`), grouping and aggregation (`groupby()`), and route DataFrame row streams dynamically using Structural Pattern Matching (`match-case`).


2. Foundations of Numerical Computing: NumPy (`np.ndarray`)

A standard Python list is an array of pointers pointing to scattered Python objects in memory. In contrast, a NumPy Array (np.ndarray) is a **homogeneous, contiguous block of memory** allocated directly in C. This architecture eliminates Python object pointer overhead and enables the CPU to execute SIMD (Single Instruction, Multiple Data) parallel vector instructions!

# Installing NumPy and pandas dependencies:
pip install numpy pandas
    

1. Python Native List vs NumPy Array Architecture

  • Data Homogeneity
  • Heterogeneous (Holds mixed object types)
  • Strictly Homogeneous (All elements share identical primitive C type)
  • Memory Allocation Layout
  • Array of memory pointers scattered across heap
  • Contiguous Memory Block allocated sequentially in RAM
  • Execution Paradigm
  • Iterative Python for loop overhead
  • Vectorized Operations compiled in C/Fortran
  • Math Multiplication Speed
  • Baseline Speed ($1\times$)
  • 50x to 100x Faster for large datasets!
Memory & Performance Dimension Standard Python List (`list`) NumPy Array (`np.ndarray`)
NUMPY_VECTORIZATION_DEMO.PY
import numpy as np
import time

# 1. Instantiating a 1D and 2D NumPy Array
arr_1d = np.array([10, 20, 30, 40, 50], dtype=np.float64)
matrix_2d = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int32)

print("=== 1. NumPy Array Structure Inspection ===")
print("1D Array         :", arr_1d)
print("1D Shape         :", arr_1d.shape)
print("2D Matrix        :\n", matrix_2d)
print("2D Matrix Shape  :", matrix_2d.shape)

# 2. Vectorized Math Operations vs Python Loops (No 'for' loops required!)
prices_usd = np.array([100.0, 250.50, 499.99, 1200.0])
exchange_rate_inr = 83.50

# Vectorized multiplication applied to entire array instantaneously!
prices_inr = prices_usd * exchange_rate_inr

print("\n=== 2. Vectorized Math Calculation ===")
print("Prices in USD:", prices_usd)
print("Prices in INR:", prices_inr.round(2))

# 3. Array Broadcasting Demonstration (Adding 1D array to 2D matrix)
grid = np.zeros((3, 3))
row_offset = np.array([10, 20, 30])
broadcast_result = grid + row_offset  # Automatically expands dimensions!

print("\n=== 3. Broadcasting Output Grid ===")
print(broadcast_result)
OUTPUT
=== 1. NumPy Array Structure Inspection ===
1D Array         : [10. 20. 30. 40. 50.]
1D Shape         : (5,)
2D Matrix        :
 [[1 2 3]
 [4 5 6]]
2D Matrix Shape  : (2, 3)

=== 2. Vectorized Math Calculation ===
Prices in USD: [ 100.    250.5   499.99 1200.  ]
Prices in INR: [  8350.    20916.75  41749.16 100200.  ]

=== 3. Broadcasting Output Grid ===
[[10. 20. 30.]
 [10. 20. 30.]
 [10. 20. 30.]]

3. Tabular Data Analysis: pandas DataFrames & Series

While NumPy provides low-level array math, real-world data contains mixed types (strings, timestamps, floats), missing values (NaN), and column header labels.

pandas introduces two essential data structures:

  • pandas Series: A 1-dimensional labeled array capable of holding any data type (equivalent to a single typed database column with an index).
  • pandas DataFrame: A 2-dimensional labeled tabular data structure comprised of aligned columns and rows (equivalent to a full database table or Excel spreadsheet).

1. Advanced Indexing: `loc` vs `iloc`

  • df.loc[row_label, col_label]
  • Label-Based Indexing
  • df.loc[df['status'] == 'ACTIVE', 'balance']
  • Selects data rows and columns using explicit string header names or boolean conditions.
  • df.iloc[row_idx, col_idx]
  • Integer Position Indexing
  • df.iloc[0:5, 0:3]
  • Selects data rows and columns using zero-based integer positional coordinates strictly.
Indexer Syntax Selection Axis Basis Example Usage Pattern Primary Purpose Description
PANDAS_DATAFRAME_CORE_DEMO.PY
import pandas as pd
import numpy as np

# Creating sample dictionary for DataFrame construction
raw_data_map = {
    "account_id": ["ACC_101", "ACC_102", "ACC_103", "ACC_104", "ACC_105"],
    "region": ["NORTH", "WEST", "NORTH", "EAST", "WEST"],
    "revenue": [12500.0, 8400.0, np.nan, 3100.0, 15000.0],  # Contains missing NaN!
    "active": [True, True, False, True, True]
}

# 1. Instantiating pandas DataFrame
df = pd.DataFrame(raw_data_map)

print("=== 1. Core DataFrame Inspection ===")
print(df)
print("\nDataFrame Shape:", df.shape)
print("Data Types:\n", df.dtypes)

# 2. Label Indexing via .loc and Boolean Filtering
north_accounts = df.loc[df["region"] == "NORTH", ["account_id", "revenue"]]

print("\n=== 2. Boolean Masked Sub-selection (.loc) ===")
print(north_accounts)

# 3. Positional Slicing via .iloc (First 2 rows, first 3 columns)
print("\n=== 3. Positional Integer Slicing (.iloc) ===")
print(df.iloc[0:2, 0:3])
OUTPUT
=== 1. Core DataFrame Inspection ===
  account_id region  revenue  active
0    ACC_101  NORTH  12500.0    True
1    ACC_102   WEST   8400.0    True
2    ACC_103  NORTH      NaN   False
3    ACC_104   EAST   3100.0    True
4    ACC_105   WEST  15000.0    True

DataFrame Shape: (5, 4)
Data Types:
 account_id     object
region         object
revenue       float64
active           bool
dtype: object

=== 2. Boolean Masked Sub-selection (.loc) ===
  account_id  revenue
0    ACC_101  12500.0
2    ACC_103      NaN

=== 3. Positional Integer Slicing (.iloc) ===
  account_id region  revenue
0    ACC_101  NORTH  12500.0
1    ACC_102   WEST   8400.0

4. Data Cleaning, Missing Values & Aggregations

Real-world datasets ingested from web scrapers, APIs, or databases are rarely clean. They contain missing values (`NaN`), duplicate rows, or unformatted text strings.

1. Handling Missing Data (`isna()`, `dropna()`, `fillna()`)

  • df.isna().sum(): Returns count of missing `NaN` values per column.
  • df.dropna(subset=['col']): Drops table rows containing missing values in specified columns.
  • df['col'].fillna(value): Replaces missing `NaN` values with constant defaults or computed means.

2. Grouping and Aggregation (`groupby()`)

The groupby() method implements the classic Split-Apply-Combine workflow: splitting data into groups based on category keys, applying statistical aggregations (e.g., sum(), mean(), count()), and combining results into a summary table!

PANDAS_CLEANING_GROUPBY_DEMO.PY
import pandas as pd
import numpy as np

data = {
    "store": ["Store_A", "Store_A", "Store_B", "Store_B", "Store_C", "Store_C"],
    "category": ["Tech", "Office", "Tech", "Office", "Tech", "Office"],
    "sales": [5000.0, np.nan, 7000.0, 1200.0, np.nan, 3400.0]
}

df_sales = pd.DataFrame(data)

print("=== 1. Original Dataset with Missing Values (NaN) ===")
print(df_sales)

# 2. Cleaning Missing Values: Filling NaN sales with column median
mean_sales_val = df_sales["sales"].mean()
df_sales["sales"] = df_sales["sales"].fillna(mean_sales_val)

print("\n=== 2. Dataset Post fillna() Processing ===")
print(df_sales)

# 3. Grouping by Category and Computing Summary Statistics
category_summary = df_sales.groupby("category")["sales"].agg(["count", "mean", "sum"]).reset_index()

print("\n=== 3. GroupBy Aggregation Summary (Split-Apply-Combine) ===")
print(category_summary)
OUTPUT
=== 1. Original Dataset with Missing Values (NaN) ===
     store category   sales
0  Store_A     Tech  5000.0
1  Store_A   Office     NaN
2  Store_B     Tech  7000.0
3  Store_B   Office  1200.0
4  Store_C     Tech     NaN
5  Store_C   Office  3400.0

=== 2. Dataset Post fillna() Processing ===
     store category   sales
0  Store_A     Tech  5000.0
1  Store_A   Office  4150.0
2  Store_B     Tech  7000.0
3  Store_B   Office  1200.0
4  Store_C     Tech  4150.0
5  Store_C   Office  3400.0

=== 3. GroupBy Aggregation Summary (Split-Apply-Combine) ===
  category  count         mean      sum
0   Office      3  2916.666667   8750.0
1     Tech      3  5383.333333  16150.0

5. File I/O Integration: CSV and Database Interoperability

pandas serves as a universal data bridge, reading and writing tabular files across formats effortlessly:

  • pd.read_csv("file.csv") & df.to_csv("file.csv", index=False): Reads/writes CSV spreadsheets.
  • pd.read_sql("SELECT * FROM table", conn): Queries SQL database tables directly into DataFrames!
  • pd.read_json("data.json"): Converts JSON data streams directly into DataFrames.

6. Combining DataFrame Records with `match-case` Pattern Matching

Building automated data analytics dispatchers involves iterating through DataFrame row dictionaries (`df.to_dict(orient="records")`) and evaluating metrics using Python 3.10+ `match-case` Structural Pattern Matching.

MATCH_CASE_PANDAS_DISPATCHER.PY
import pandas as pd

def process_dataframe_record_stream(data_df: pd.DataFrame):
    """
    Converts DataFrame rows to dictionaries and dispatches records using match-case.
    Demonstrates evaluating pandas analytical rows dynamically.
    """
    # Converting DataFrame to list of record dictionaries
    records = data_df.to_dict(orient="records")

    print("=== Pattern Matched DataFrame Analytical Stream ===")
    for row in records:
        match row:
            case {"region": str(reg), "sales": float(s), "margin": float(m)} if s >= 10000.0 and m >= 0.25:
                print(f"[HIGH_PERFORMER] Region '{reg}': Outstanding sales ${s:,.2f} with {m*100:.0f}% profit margin!")

            case {"region": str(reg), "sales": float(s)} if s < 2000.0:
                print(f"[UNDERPERFORMER_ALERT] Region '{reg}': Sales dropped below target -> ${s:,.2f}")

            case {"region": str(reg), "sales": float(s), "margin": float(m)}:
                print(f"[STANDARD_PERFORMANCE] Region '{reg}': Sales ${s:,.2f} | Margin: {m*100:.0f}%")

            case _:
                print(f"[UNHANDLED_SCHEMA] Unrecognized row structure: {row}")

# Testing Analytics Dispatcher
sample_analytics_df = pd.DataFrame([
    {"region": "NORTH", "sales": 15000.0, "margin": 0.30},
    {"region": "SOUTH", "sales": 1200.0, "margin": 0.10},
    {"region": "WEST", "sales": 6500.0, "margin": 0.18}
])

process_dataframe_record_stream(sample_analytics_df)
OUTPUT
=== Pattern Matched DataFrame Analytical Stream ===
[HIGH_PERFORMER] Region 'NORTH': Outstanding sales $15,000.00 with 30% profit margin!
[UNDERPERFORMER_ALERT] Region 'SOUTH': Sales dropped below target -> $1,200.00
[STANDARD_PERFORMANCE] Region 'WEST': Sales $6,500.00 | Margin: 18%

7. Frequently Asked Interview Questions with Answers

Q1: Why are NumPy arrays significantly faster than standard Python lists for mathematical computations?
Answer: NumPy arrays store elements in a homogeneous, contiguous block of C memory rather than an array of pointers to scattered Python objects. This eliminates dynamic type-checking overhead and allows C-compiled SIMD instructions to operate on entire array memory blocks simultaneously.
Q2: What is the primary difference between `.loc` and `.iloc` in pandas?
Answer: .loc performs **Label-Based Indexing** using explicit row/column string header names or boolean conditions. .iloc performs **Positional Integer Indexing** using zero-based integer coordinates strictly regardless of string label names.
Q3: How does Array Broadcasting operate in NumPy?
Answer: Broadcasting allows NumPy to execute vectorized arithmetic operations on arrays of different dimensions without making redundant memory copies. NumPy automatically aligns and expands the smaller array across the dimensions of the larger array according to compatibility rules.
Q4: How do `dropna()` and `fillna()` handle missing `NaN` values in a DataFrame?
Answer: dropna() removes rows or columns containing missing NaN values permanently or along specified axes. fillna(value) replaces missing NaN entries with constant values, column medians, or interpolated averages.
Q5: What is the "Split-Apply-Combine" pattern in pandas `groupby()`?
Answer: The Split-Apply-Combine workflow splits a DataFrame into logical sub-groups based on categorical key columns, applies statistical functions (like sum(), mean(), or custom aggregations) to each sub-group independently, and combines aggregated outputs back into a structured summary DataFrame.

8. Homework & Practical Assignments

Task 1: NumPy Array Math and pandas Data Cleanup Task

Create a script named numpy_pandas_task.py inside your lesson_59 folder:

  • Import numpy and pandas.
  • Create a 2D NumPy array of random float values ($4 \times 4$) and compute row-wise sums and column-wise means.
  • Construct a pandas DataFrame containing missing `NaN` values in a numerical column.
  • Fill missing `NaN` values using the column median and drop duplicate rows.
  • Print formatted summary outputs using f-strings.

Task 2: Pattern-Matched DataFrame Analytical Dispatcher

Create a script named df_analytics_task.py:

  • Build function analyze_metric_row(row: dict) -> str parsing row metric dictionaries.
  • Write a match-case dispatcher:
    • case {"cpu_usage": float(cpu)} if cpu >= 90.0 → Return "CRITICAL_CPU_SPIKE_ALERT".
    • case {"ram_usage": float(ram)} if ram >= 85.0 → Return "HIGH_RAM_WARNING".
    • case {"status": "OFFLINE"} → Return "SERVER_OFFLINE".
    • case _ → Return "METRIC_NOMINAL".
  • Create a sample DataFrame with server metrics, iterate through row dicts, and print classification results.

Task 3: Master Review Capstone Project — Enterprise High-Performance Analytics & Data Science OS (`data_analytics_os.py`)

Create a script named data_analytics_os.py inside your lesson_59 folder. This assignment tests and integrates **ALL concepts learned across Lessons 1 through 59**.

Project Architectural Requirements Specification:

  1. NumPy & pandas Analytics Architecture (Lesson 59):
    • Perform vectorized array operations via NumPy and construct analytical pandas DataFrames.
    • Execute data cleaning (`fillna`, `dropna`), advanced indexing (`loc`), and category aggregations (`groupby()`).
    • Export processed summary tables to CSV using df.to_csv() and read inputs via pd.read_csv().
  2. FastAPI & Web Framework Integration (Lesson 58):
    • Expose analytical query endpoints using asynchronous FastAPI path operation functions (`async def`) and Pydantic validation models (`BaseModel`).
  3. Flask & Web Development Integration (Lesson 57):
    • Incorporate route parameter patterns and view handlers.
  4. RPA & Office Automation Integration (Lesson 56):
    • Generate Excel summary reports via openpyxl and export email alerts using email.message.EmailMessage when analytics thresholds breach limits.
  5. Web Scraping Integration (Lesson 55):
    • Extract HTML elements using BeautifulSoup4 (`bs4`) to populate DataFrame source tables.
  6. HTTP APIs & requests Integration (Lesson 54):
    • Fetch remote operational datasets via requests.Session().
  7. SQLite Persistence Integration (Lesson 53):
    • Persist DataFrame analytical records into an SQLite database table using df.to_sql() or parameterized SQL statements.
  8. Security, Performance & Memory Hardening (Lesson 52):
    • Use __slots__ across core domain models for memory optimization.
    • Read secrets and data paths from environment variables using os.environ.
  9. Packaging & Distribution Integration (Lesson 51):
    • Include a programmatically generated pyproject.toml package specification string and an argparse CLI entry point structure.
  10. Clean Code, Documentation & Refactoring (Lesson 50):
    • Apply SOLID principles, DRY, and Google Style Docstrings across all functions and classes.
  11. Testing & Quality Assurance (Lessons 47-48):
    • Include unit tests verified via pytest fixtures testing DataFrame transformations.
  12. Asyncio & Concurrency Integration (Lessons 45-46):
    • Incorporate thread pool workers or async event loops for parallel multi-dataset analysis.
  13. Temporal & RegEx Text Processing (Lessons 43-44):
    • Parse UTC-aware timestamps using datetime and zoneinfo.ZoneInfo.
    • Pre-compile RegEx patterns with Named Groups for parsing dataset string column entries.
  14. Type Hints, Generics & Static Safety (Lesson 42):
    • Apply explicit modern type annotations (X | Y, list[str], dict[str, Any]) throughout all functions and classes.
  15. Metaprogramming, Closures & Decorators (Lessons 40-41):
    • Build function factories and 3-level configurable decorators with @functools.wraps.
  16. Iterators & Generators (Lesson 39):
    • Implement generator functions streaming DataFrame row chunks lazily with $O(1)$ memory.
  17. Full OOP Architecture (Lessons 32-38):
    • Define abstract base class BaseAnalyticsEngine(ABC) and concrete Data Classes DataMetricRecord and AnalyticsAudit.
    • Build composite manager DataAnalyticsOS composing database persistence drivers and analytics handles.
  18. Observability & Fault Tolerance (Lessons 29-31):
    • Set up multi-handler logging to console and data_analytics.log file.
    • Incorporate developer assertions (assert) verifying DataFrame length bounds.
    • Define custom exception hierarchy (DataAnalyticsOSError, DataTransformationError).
  19. Context Managers & Persistence Layer (Lessons 27-30):
    • Use custom class-based context managers to manage temp file cleanup.
    • Persist JSON payload backups to analytics_db.json and export CSV reports to analytics_audit.csv using pathlib.Path.
  20. Nested Collections & Comprehensions (Lessons 21-26):
    • Maintain in-memory registry dictionaries mapping IDs to Data Class Instances.
    • Use List and Dictionary Comprehensions to clean and transform records.
  21. Advanced Function Parameters & Scope (Lessons 15-17):
    • Structure logic into pure modular functions with type hints, docstrings, early return Guard Clauses, and *args / **kwargs logging.
  22. Indefinite & Definite Loops (Lessons 13-14):
    • Run the interactive CLI interface inside a continuous while True menu loop.
    • Iterate through output reports using for loops with enumerate() and .items().
  23. Pattern Matching CLI Dispatcher (Lesson 12):
    • Process user CLI command tokens inside a match-case block with data analytics match guards:
      • case ["LOAD", "CSV", filepath] → Read CSV into pandas DataFrame and display summary info.
      • case ["CLEAN", "MISSING"] → Execute fillna() data cleaning sequence.
      • case ["GROUPBY", col_name] → Run category aggregation using pandas groupby().
      • case ["AUDIT", "ROWS"] → Route DataFrame row dicts using match-case pattern dispatcher.
      • case ["EXPORT", "CSV"] → Export analytical DataFrame results to CSV.
      • case ["EXIT" | "QUIT"] → Terminate session safely using a sentinel flag.
      • case _ → Output command error message.
  24. Conditionals, Formatting & Foundations (Lessons 1-11):
    • Sanitize all inputs using .strip() and .upper().
    • Format tabular reports using f-strings with field width alignment specifiers (:<15, :>10) and clear visual borders.

9. File & Workspace Directory Structure

Standard Course Workspace Layout:

Ensure all exercise files are stored inside their corresponding lesson directories:

python_mastery_course/
│
├── lesson_01/ ... lesson_58/
│
└── lesson_59/
    ├── numpy_vectorization_demo.py
    ├── pandas_dataframe_core_demo.py
    ├── pandas_cleaning_groupby_demo.py
    ├── match_case_pandas_dispatcher.py
    ├── numpy_pandas_task.py          <-- (Task 1)
    ├── df_analytics_task.py          <-- (Task 2)
    └── data_analytics_os.py          <-- (Task 3: Master Review Capstone)
        

10. What We Will Learn Next

Next Up: Lesson 60 — Capstone: Production-Ready Task Manager API

Congratulations on completing Lesson 59! We have now reached the ultimate, final culmination of our Python Mastery Series: Lesson 60 Grand Capstone!

In the final capstone lesson, we will synthesize ALL 59 lessons into a single Production-Grade System:

  • Architecting an enterprise multi-tier Asynchronous Task Manager REST API Engine.
  • Integrating FastAPI, SQLite database persistence, Pydantic validation, and background Task workers.
  • Automating pandas/NumPy analytical summary reports, Excel exports via openpyxl, and email alerts.
  • Full test suite validation using pytest, fixtures, mocking, and 100% coverage checks.
  • Complete packaging specification with pyproject.toml and global CLI execution.
  • Mastering Structural Pattern Matching (`match-case`) across all system dispatchers!

📝 Live Lesson Practice

HTML/CSS JavaScript Python C++ C PHP
⌨️ Practice Inputs (लाइव इनपुट भरें) (खाली होने पर RED, भरने पर GREEN underline)
💻 Code Editor (Monaco VS Code Engine)
👀 Live Preview
Address Contact

+91 7877547686

E-mail

onlinecbtportal@gmail.com

Helpline Number

+91 7877547686


Click To Download
Get it on Google Play

ऐप डाउनलोड करने
के लिए Google Play पर
उपलब्ध है

WhatsApp Chat