Data Manipulation with Pandas: Key Functions and Techniques

Posted on Nov 9, 2024 | Estimated Reading Time: 15 minutes

Introduction

Pandas is a powerful and versatile library for data manipulation and analysis in Python. It provides data structures like DataFrame and Series which are essential for handling structured data. This guide covers key functions and techniques in Pandas that every data scientist should know, especially when preparing for interviews.


1. Importing Pandas and Reading Data

Before you can manipulate data, you need to read it into your Python environment.

Importing Pandas

import pandas as pd
                    

Reading Data from CSV

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

Reading Data from Excel

df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
                    

Reading Data from SQL Database

import sqlite3

conn = sqlite3.connect('database.db')
df = pd.read_sql_query('SELECT * FROM table_name', conn)
                    

Why It's Important: Knowing how to import data from various sources is the first step in any data manipulation task.


2. DataFrame Basics

Understanding the basic structure and properties of a DataFrame.

Exploring the DataFrame

df.head()          # View the first 5 rows
df.tail()          # View the last 5 rows
df.info()          # Get a summary of the DataFrame
df.describe()      # Get statistical summary
                    

Accessing Columns

df['column_name']          # Access a single column
df[['col1', 'col2']]    # Access multiple columns
                    

Adding New Columns

df['new_column'] = df['col1'] + df['col2']
                    

Why It's Important: Mastering DataFrame basics is essential for efficient data manipulation.


3. Selecting and Filtering Data

Learn how to select specific data based on conditions.

Indexing and Slicing

df.iloc[0:5, 0:3]     # Select rows by position
df.loc[0:5, ['col1', 'col2']]  # Select rows and columns by labels
                    

Conditional Selection

df[df['col1'] > 50]          # Rows where col1 > 50
df[(df['col1'] > 50) & (df['col2'] == 'A')]  # Multiple conditions
                    

isin() Function

df[df['col2'].isin(['A', 'B'])]
                    

Why It's Important: Efficient data selection is crucial for data analysis and feature engineering.


4. Handling Missing Data

Techniques to detect, remove, and fill missing values.

Detecting Missing Values

df.isnull()          # Check for null values
df.isnull().sum()   # Count of null values per column
                    

Dropping Missing Values

df.dropna()                  # Drop rows with any null values
df.dropna(axis=1)            # Drop columns with any null values
df.dropna(thresh=2)          # Drop rows with at least 2 non-null values
                    

Filling Missing Values

df.fillna(0)                 # Replace null values with 0
df['col1'].fillna(df['col1'].mean(), inplace=True)  # Replace with mean
                    

Why It's Important: Handling missing data correctly ensures the integrity of your analysis.


5. Data Aggregation with GroupBy

Summarize data using groupby operations.

Basic GroupBy

df_grouped = df.groupby('col1')
df_grouped['col2'].mean()    # Mean of col2 for each group in col1
                    

Multiple Aggregations

# Group the DataFrame by 'col1', then calculate the mean of 'col2' and the sum of 'col3' for each group
df_grouped = df.groupby('col1').agg({'col2': 'mean', 'col3': 'sum'})
                    

Resetting Index

df_grouped.reset_index(inplace=True)
                    

Why It's Important: Grouping and aggregating data helps in deriving insights and preparing data for modeling.


6. Merging and Joining Data

Combine multiple DataFrames with different joining methods.

Concatenation

df_combined = pd.concat([df1, df2], axis=0)  # Stack vertically
df_combined = pd.concat([df1, df2], axis=1)  # Stack horizontally
                    

Merge

# Inner join: Returns rows with matching keys in both DataFrames.
df_merged = pd.merge(df1, df2, on='key_column', how='inner')  # Inner join

# Left join: Returns all rows from the left DataFrame and matching rows from the right.
df_merged = pd.merge(df1, df2, on='key_column', how='left')   # Left join

# Right join: Returns all rows from the right DataFrame and matching rows from the left.
df_merged = pd.merge(df1, df2, on='key_column', how='right')  # Right join

# Outer join: Returns all rows from both DataFrames, filling in missing matches with NaNs.
df_merged = pd.merge(df1, df2, on='key_column', how='outer')  # Outer join
                    

Join

df_joined = df1.join(df2.set_index('key_column'), on='key_column')  # Join on index

Cross Join

df_cross = df1.merge(df2, how='cross')  # Cartesian product

Why It's Important: Joining datasets allows you to combine information from different sources, often essential in data analysis.


7. Reshaping Data

Transform the layout of your DataFrame.

Pivot Table

# Input
data = {
    'col1': ['A', 'A', 'B', 'B'],
    'col2': ['X', 'Y', 'X', 'Y'],
    'col3': [10, 20, 30, 40],
    'col4': [5, 6, 7, 8]
}
df = pd.DataFrame(data)

# Creating a pivot table with 'col1' as rows, 'col2' as columns, and calculating mean of 'col3' values
df_pivot = df.pivot_table(index='col1', columns='col2', values='col3', aggfunc='mean')
print(df_pivot)
# Output
col2     X     Y
col1            
A      10.0  20.0
B      30.0  40.0

Melting

# Melting the DataFrame, keeping 'col1' as identifier, and unpivoting 'col3' and 'col4' into long format
df_melted = pd.melt(df, id_vars=['col1'], value_vars=['col3', 'col4'])
print(df_melted)
# Output
  col1 variable  value
0    A     col3     10
1    A     col3     20
2    B     col3     30
3    B     col3     40
4    A     col4      5
5    A     col4      6
6    B     col4      7
7    B     col4      8

Stack and Unstack

# Stacking columns into rows
df_stacked = df.set_index(['col1', 'col2']).stack()
print(df_stacked)

# Unstacking the stacked DataFrame back to columns
df_unstacked = df_stacked.unstack()
print(df_unstacked)
#Stacked DataFrame:
col1  col2       
A   X     col3    10
          col4     5
    Y     col3    20
          col4     6
B   X     col3    30
          col4     7
    Y     col3    40
          col4     8


# Unstacked Output
       col3      col4     
col2     X   Y     X    Y
col1                      
A      10.0 20.0   5.0  6.0
B      30.0 40.0   7.0  8.0

Why It's Important: Reshaping data is essential for preparing datasets for analysis or visualization.


8. Working with Time Series Data

Handle date and time data effectively.

Parsing Dates

df['date'] = pd.to_datetime(df['date_column'])
                    

Setting Date as Index

df.set_index('date', inplace=True)
                    

Resampling

df_resampled = df.resample('M').mean()  # Resampling by month to calculate the mean for each month
                    

Time-based Selection

df['2021-01']          # Select data for January 2021
df['2021-01-01':'2021-01-31']  # Select data between two dates
                    

Why It's Important: Time series analysis is a key aspect of data science, especially in forecasting and trend analysis.


9. Applying Functions

Use custom functions to transform your data.

Using apply() Function

def add_prefix(x):
    return 'ID_' + str(x)

df['new_col'] = df['col1'].apply(add_prefix)
                    

Lambda Functions

df['col2'] = df['col2'].apply(lambda x: x * 2)
                    

Applymap() Function

Apply a function to every element of a DataFrame.

df = df.applymap(lambda x: x.strip() if isinstance(x, str) else x)
                    

Why It's Important: Custom functions allow for complex data transformations that aren't possible with built-in methods.


10. Efficient Data Operations

Optimize performance with vectorized operations.

Vectorized String Methods

df['col1'].str.upper()
df['col1'].str.contains('pattern')
                    

Vectorized Mathematical Operations

df['col2'] = df['col2'] * 100
df['col3'] = df['col3'] / df['col4']
                    

Using NumPy Functions

import numpy as np

df['log_col'] = np.log(df['col5'])
                    

Why It's Important: Vectorized operations are faster and more efficient than looping through DataFrame rows.


Sample Interview Questions

Question 1: How do you handle missing data in a DataFrame?

Answer: Missing data can be handled by detecting missing values using isnull() or notnull(), and then either dropping them using dropna() or filling them using fillna(). The choice depends on the context and the importance of the missing values.


Question 2: What is the difference between merge and join in Pandas?

Answer: Both are used to combine DataFrames. merge is a function that allows you to specify the columns to join on, similar to SQL joins, and is more flexible. join is a method of DataFrame that is convenient for joining on the index or a key column.


Question 3: Explain how you would reshape a DataFrame from wide to long format.

Answer: To reshape a DataFrame from wide to long format, you can use the melt() function. It unpivots a DataFrame from wide format to long format, making it suitable for certain types of data analysis and visualization.


Conclusion

Mastering Pandas is crucial for efficient data manipulation and analysis in Python. The functions and techniques covered in this guide are fundamental for any data scientist. Practice using these methods on real datasets to strengthen your understanding and prepare for technical interviews.


Additional Resources


Author's Note

Thank you for reading! If you have any questions or comments, feel free to reach out. Stay tuned for more articles in this series.

← Back to Blogs