1. Introduction to Pandas
Need and Overview of Pandas
- The Data Science Bottleneck: Real-world data is rarely immediately usable. It is typically massive, unstructured, noisy, and unclean.
- The Role of Pandas: Instead of writing boilerplate code to read, clean, restructure, and analyze data from scratch, Pandas serves as an open-source Python library that provides highly optimized data structures and functions.
- Prerequisite for ML: Knowing Pandas is an essential step before diving into Machine Learning and Generative AI.
Importing Pandas
By convention, Pandas is imported using the standard aliaspd:
Setup and Installation
- Cloud Environments (Recommended for Beginners): Google Colab runs on the cloud, requiring zero local setup, while tracking and saving progress automatically.
- Local Environments: You can install Jupyter Notebook, VS Code, or PyCharm. To get started with Jupyter Notebook, install it via pip:
2. Pandas Data Structures
Pandas has two primary data structures: Series (1D) and DataFrame (2D).Series
A Series is a 1-dimensional array-like object. While it looks like a Python list, it is built with optimized functions (like calculatingmean(), median(), and sum()) that standard Python lists lack.
DataFrame
A DataFrame is a 2-dimensional, table-like structure with labeled rows and columns. It can be thought of as a spreadsheet or a SQL table, offering rich tools for filtering, manipulation, and analysis.DataFrame vs 2D Arrays
- Heterogeneous Data: A DataFrame can hold multiple different data types across different columns (e.g., one column of
str, another ofint, and another offloat). - Homogeneous Data: A traditional 2D array (such as in NumPy) is limited to holding a single, uniform data type across all elements.
3. Creating DataFrames
Creating DataFrames from Different Sources
You can construct DataFrames programmatically from nested Python lists or dictionaries.Common File Formats for Datasets
- CSV, Excel, JSON: Universal and compatible, but often slow and storage-heavy. Excel is especially bulky because it packs rich formatting and metadata.
- Parquet and Feather: Columnar binary formats optimized for big data. They employ built-in compression and are highly efficient. E.g., a 1 GB CSV file can be compressed to ~100 MB in Parquet (Apache ecosystem) or ~200–300 MB in Feather.
Reading Data from CSV Files
Pandas provides dedicated reading and exporting tools:4. Exploring Data
Viewing Data (head(), tail(), sample())
head(n): Returns the firstnrows (defaults to 5) to verify data is loaded properly.tail(n): Returns the lastnrows (defaults to 5).sample(n, frac, random_state): Selects random rows. This is superior tohead()andtail()for checking sorted datasets.n: exact number of rows.frac: fraction of rows (e.g.,frac=0.1is 10% of the dataset).random_state: set to an integer seed to guarantee the same random row selection across runs.
DataFrame Information
- Labels (Index & Columns): Access labels directly as properties.
- Shape: Returns a tuple indicating dimensionality
(rows, columns). - Size: Returns an integer of total elements (rows × columns).
info(): Lists column names, non-null counts, indices, data types, and memory usage.describe(): Computes descriptive statistics (mean, median, standard deviation, min, max, percentiles) for numerical columns.
5. Accessing Data
Row and Column Selection
1. loc[] (Label-Based Indexing)
Accesses rows/columns by their label names. Slicing with loc is fully inclusive of both endpoints.
2. iloc[] (Integer Position-Based Indexing)
Accesses rows/columns by their integer index positions. Slicing with iloc is exclusive of the upper bound.
3. at[] (Optimized Label-Based Scalar Access)
Designed to quickly fetch or update a single, specific value. Built on top of NumPy, it bypasses safety checks and is faster than .loc[]. Slices are not supported.
4. iat[] (Optimized Integer-Based Scalar Access)
Bypasses overhead checks to retrieve a single value by integer index. Requires both row and column indices.
Accessing Columns: Shorthand vs Dot Notation
Columns can be queried using brackets or attributes:- Bracket (Shorthand) Notation:
obesity_data['family_history']. For multiple columns, pass a nested list:obesity_data[['age', 'weight']]. Highly recommended because it easily handles column names with spaces or special characters. - Dot Notation:
obesity_data.family_history. Fails when column names contain spaces (e.g.,family historyinstead offamily_history).
6. Filtering Data
Filtering with Conditions (Boolean Indexing)
By applying comparison operations to columns, Pandas generates a “Boolean Mask” of True/False values, which.loc[] uses to extract corresponding rows.
Multiple Conditions
Combine multiple conditional filters using bitwise operators:&for AND (all conditions must be true)|for OR (at least one condition must be true)- Crucial Rule: Each conditional block must be enclosed in parentheses
()to maintain correct order of operations.
Regular Expressions (Regex)
You can search text patterns inside object/string columns using.str methods.
7. Updating and Transforming Data
All updates modify the original DataFrame structure.Updating Data using loc[]
Update values across specific labels:
Updating using iloc[], at[], iat[]
Transforming Data with apply()
.apply() allows running a custom function along an entire row or column. By default, it runs column-wise (axis=0).
- Assignment is Required: By default,
.apply()does not edit in-place; you must assign it back.
Using Lambda Functions with apply()
For simple, temporary transformations, write a short, anonymous lambda function directly inside .apply() to avoid writing a full function definition.
Transforming Data with where() (Vectorized Alternative)
For simple conditions, NumPy’s vectorized function np.where(condition, value_if_true, value_if_false) is significantly faster and more computationally efficient than .apply().
np.where() vs apply()
Both np.where() and apply() are used to transform data, but they are designed for different purposes and are commonly used in different libraries.
Using np.where()
Use np.where() when you want to replace values based on a condition.
Syntax
Using apply()
Use apply() when the transformation requires a custom function.
Example
Using apply() with a Lambda Function
Which One Should You Use?
Key Differences
np.where()is a vectorized NumPy function that performs conditional replacement efficiently.apply()is a Pandas method that applies a user-defined function to each element, row, or column.- For simple conditional operations,
np.where()is generally faster and preferred. - For complex transformations involving multiple conditions or calculations,
apply()provides greater flexibility.
Rule of Thumb:
Usenp.where()for simple conditional replacement andapply()for custom or complex transformations.
8. Column Operations
Inserting Columns
Use.insert(loc, column, value) to add a new column at a specific index location.
Dropping Columns
The.drop(columns=[...]) method does not modify the original data unless you explicitly assign it back or set inplace=True.
Deleting Columns
Use Python’s built-indel keyword to instantly remove the column in-place.
Renaming Columns
Use.rename(columns={old_name: new_name}). Requires inplace=True or assignment.
9. Combining Data
Merging DataFrames (SQL Joins)
You can perform relational merges on common key columns usingpd.merge(left_df, right_df, how, on).
Setup Example DataFrames:
- Inner Join (
how='inner'): Returns only rows where keys match in both DataFrames (intersection). - Outer Join (
how='outer'): Returns all rows, insertingNaNwhere matches are missing (union). - Left Join (
how='left'): Retains all rows from the left DataFrame (df1), introducingNaNfor missing right matches. - Right Join (
how='right'): Retains all rows from the right DataFrame (df2), introducingNaNfor missing left matches.
Different Column Names
If the key columns are named differently (e.g.,ID_1 and ID_2), use left_on and right_on:
Concatenating DataFrames (Stacking)
pd.concat([df1, df2], axis) stacks DataFrames vertically or horizontally.
- Vertical Stacking (
axis=0): Stack rows on top of each other. - Horizontal Stacking (
axis=1): Stack columns side-by-side.
10. Handling Missing Values
NaN (Not a Number) represents missing or undefined values in datasets.
Detecting Missing Values
isna(): Returns Boolean mask whereTruemarks missing values.notna(): Returns Boolean mask whereTruemarks populated values.
Filling Missing Values (fillna())
Replace null values with meaningful data. Requires assignment or inplace=True.
Removing Missing Values (dropna())
Completely drop rows or columns containing missing values.
11. Data Aggregation
Grouping Data using groupby()
Group row records by unique category values to analyze statistics within subgroups (e.g., comparing height across genders).
12. Working with String Data
Pandas provides a dedicated set of string manipulation methods under the.str accessor. These operations are fully vectorized, allowing you to manipulate entire text columns efficiently.
Common String Operations
Checking Substrings
13. Working with Dates and Time
Datasets often contain date information stored as strings. Pandas provides powerful tools to parse, extract, and perform calculations on date columns using thepd.to_datetime() function and the .dt accessor.
Converting to Datetime
Convert string columns into actual datetime objects so Pandas can understand dates chronologically:Extracting Date Parts
Once a column is converted todatetime64, you can extract specific parts (year, month, day, day name) using the .dt accessor:
Calculating Date Differences (Timedelta)
You can subtract dates directly to calculate durations:Practice and Next Steps
Before moving to the next section, make sure to practice your Pandas skills using the interactive notebook:Pandas Practice Exercise
Practice your skills using the interactive notebook.💻 VS Code | 🚀 Colab | 📥 Download
Next Library: Matplotlib
Learn how to create static, animated, and interactive visualizations in Python.