Python Pandas 教程:快速掌握数据清洗与分析
在当今数据驱动的世界中,数据已成为各行各业的宝贵资产。然而,原始数据往往是杂乱无章、不完整或格式不一致的。为了从数据中提取有价值的见解,我们首先需要对其进行清洗、转换和分析。Python 的 Pandas 库正是为此而生,它提供了一套强大而灵活的工具,让数据处理变得高效而愉快。
本教程将带你快速掌握 Pandas 的核心概念和常用功能,助你成为数据清洗与分析的高手。
1. 什么是 Pandas?为什么选择它?
Pandas 是基于 NumPy 构建的 Python 数据分析库,提供了高性能、易于使用的数据结构和数据分析工具。它的核心优势在于:
- 强大的数据结构:主要提供
Series(一维带标签数组) 和DataFrame(二维带标签表格数据结构)。 - 灵活的数据导入/导出:支持从多种格式(CSV, Excel, SQL 数据库, JSON, HDF5 等)读取和写入数据。
- 高效的数据操作:提供丰富的数据筛选、切片、合并、重塑、分组、聚合功能。
- 缺失数据处理:内置处理缺失值的简便方法。
- 时间序列功能:强大的时间序列处理能力。
简而言之,Pandas 是数据科学家和分析师进行数据预处理、探索性数据分析(EDA)和特征工程的首选工具。
2. 安装 Pandas
如果你还没有安装 Pandas,可以通过 pip 包管理器轻松安装:
bash
pip install pandas openpyxl # openpyxl 用于读取和写入 Excel 文件
安装完成后,你可以在 Python 脚本中导入它:
python
import pandas as pd
import numpy as np # 通常与 Pandas 一起使用
3. Pandas 核心数据结构
Pandas 提供了两种主要的数据结构:Series 和 DataFrame。
3.1 Series (系列)
Series 是一种一维带标签的数组,可以存储任何数据类型(整数、浮点数、字符串、Python 对象等)。它由数据和索引组成。
“`python
从列表中创建 Series
s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(“Series from list:\n”, s)
从字典创建 Series
data = {‘a’: 10, ‘b’: 20, ‘c’: 30}
s_dict = pd.Series(data)
print(“\nSeries from dictionary:\n”, s_dict)
“`
3.2 DataFrame (数据框)
DataFrame 是 Pandas 最常用的数据结构,可以看作是一个带行和列标签的二维表格。它由多个 Series 组成,共享同一个索引。
“`python
从字典创建 DataFrame
data = {
‘姓名’: [‘张三’, ‘李四’, ‘王五’, ‘赵六’],
‘年龄’: [25, 30, 22, 28],
‘城市’: [‘北京’, ‘上海’, ‘广州’, ‘深圳’]
}
df = pd.DataFrame(data)
print(“DataFrame from dictionary:\n”, df)
从 NumPy 数组创建 DataFrame
dates = pd.date_range(‘20230101’, periods=6)
df2 = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list(‘ABCD’))
print(“\nDataFrame from NumPy array:\n”, df2)
“`
4. 导入与导出数据
Pandas 支持多种数据格式的读写。
4.1 读取数据
“`python
读取 CSV 文件
df_csv = pd.read_csv(‘data.csv’)
读取 Excel 文件
df_excel = pd.read_excel(‘data.xlsx’, sheet_name=’Sheet1′)
读取 JSON 文件
df_json = pd.read_json(‘data.json’)
示例:创建一个CSV文件用于演示
df.to_csv(‘sample_data.csv’, index=False) # 保存DataFrame到CSV
print(“\n’sample_data.csv’ created.”)
df_sample = pd.read_csv(‘sample_data.csv’)
print(“\nRead from CSV:\n”, df_sample)
“`
4.2 导出数据
“`python
导出为 CSV 文件
df.to_csv(‘output.csv’, index=False) # index=False 不写入行索引
导出为 Excel 文件
df.to_excel(‘output.xlsx’, sheet_name=’Sheet1′, index=False)
导出为 JSON 文件
df.to_json(‘output.json’, orient=’records’)
“`
5. 数据初步探索 (EDA)
在进行数据清洗和分析之前,了解数据的基本情况至关重要。
“`python
假设我们正在处理 df_sample
print(“\n— Data Exploration —“)
print(“First 5 rows:\n”, df_sample.head()) # 查看前5行
print(“\nLast 3 rows:\n”, df_sample.tail(3)) # 查看后3行
print(“\nDataFrame Info (数据概览):\n”)
df_sample.info() # 获取 DataFrame 的摘要信息,包括数据类型、非空值数量
print(“\nDescriptive Statistics (描述性统计):\n”, df_sample.describe()) # 对数值列进行描述性统计
print(“\nDataFrame Shape (行数, 列数):\n”, df_sample.shape) # 获取 DataFrame 的维度 (行数, 列数)
print(“\nColumn Names (列名):\n”, df_sample.columns) # 获取所有列名
print(“\nData Types (数据类型):\n”, df_sample.dtypes) # 获取每列的数据类型
“`
6. 数据清洗
数据清洗是数据分析过程中最耗时但至关重要的一步。
6.1 处理缺失值
缺失值(NaN 或 None)是常见的数据问题。
“`python
创建一个带缺失值的 DataFrame 进行演示
df_missing = pd.DataFrame({
‘A’: [1, 2, np.nan, 4],
‘B’: [5, np.nan, np.nan, 8],
‘C’: [9, 10, 11, 12]
})
print(“\n— Handling Missing Values —“)
print(“Original DataFrame with missing values:\n”, df_missing)
检查缺失值
print(“\nCheck for null values:\n”, df_missing.isnull())
print(“\nTotal null values per column:\n”, df_missing.isnull().sum())
删除含有缺失值的行
df_dropna_row = df_missing.dropna()
print(“\nDataFrame after dropping rows with any NaN:\n”, df_dropna_row)
删除含有所有缺失值的行 (how=’all’)
df_dropna_all = df_missing.dropna(how=’all’)
print(“\nDataFrame after dropping rows with all NaN (if any):\n”, df_dropna_all)
填充缺失值
1. 用固定值填充
df_fill_zero = df_missing.fillna(0)
print(“\nDataFrame after filling NaN with 0:\n”, df_fill_zero)
2. 用列的均值填充
df_fill_mean = df_missing.fillna(df_missing[‘A’].mean())
print(“\nDataFrame after filling NaN in ‘A’ with its mean (and others with overall mean if not specified):\n”, df_fill_mean)
3. 使用前一个有效值填充 (forward fill)
df_ffill = df_missing.fillna(method=’ffill’)
print(“\nDataFrame after forward fill (ffill):\n”, df_ffill)
4. 使用后一个有效值填充 (backward fill)
df_bfill = df_missing.fillna(method=’bfill’)
print(“\nDataFrame after backward fill (bfill):\n”, df_bfill)
“`
6.2 删除重复值
重复行可能会影响分析结果,需要进行处理。
“`python
df_duplicates = pd.DataFrame({
‘A’: [1, 2, 2, 3, 1],
‘B’: [‘x’, ‘y’, ‘y’, ‘z’, ‘x’]
})
print(“\n— Removing Duplicates —“)
print(“Original DataFrame with duplicates:\n”, df_duplicates)
查找重复行
print(“\nCheck for duplicated rows:\n”, df_duplicates.duplicated())
删除重复行 (默认保留第一个)
df_no_duplicates = df_duplicates.drop_duplicates()
print(“\nDataFrame after dropping duplicates:\n”, df_no_duplicates)
删除重复行,保留最后一个
df_no_duplicates_last = df_duplicates.drop_duplicates(keep=’last’)
print(“\nDataFrame after dropping duplicates (keep last):\n”, df_no_duplicates_last)
基于特定列删除重复项
df_no_duplicates_A = df_duplicates.drop_duplicates(subset=[‘A’])
print(“\nDataFrame after dropping duplicates based on ‘A’ column:\n”, df_no_duplicates_A)
“`
6.3 更改数据类型
有时数据导入后类型不正确,需要手动转换。
“`python
df_types = pd.DataFrame({
‘A’: [‘1’, ‘2’, ‘3’],
‘B’: [‘4.5’, ‘5.5’, ‘6.5’],
‘C’: [‘True’, ‘False’, ‘True’]
})
print(“\n— Correcting Data Types —“)
print(“Original DataFrame data types:\n”, df_types.dtypes)
将 ‘A’ 列转换为整数
df_types[‘A’] = df_types[‘A’].astype(int)
将 ‘B’ 列转换为浮点数
df_types[‘B’] = df_types[‘B’].astype(float)
将 ‘C’ 列转换为布尔型
df_types[‘C’] = df_types[‘C’].astype(bool)
print(“\nDataFrame data types after conversion:\n”, df_types.dtypes)
“`
6.4 重命名列名
清晰的列名有助于理解数据。
“`python
print(“\n— Renaming Columns —“)
print(“Original df_sample columns:\n”, df_sample.columns)
重命名单个或多个列
df_renamed = df_sample.rename(columns={‘姓名’: ‘Name’, ‘年龄’: ‘Age’})
print(“\nDataFrame after renaming columns:\n”, df_renamed)
“`
7. 数据选择与过滤
从 DataFrame 中提取所需数据是日常操作。
7.1 选择列
“`python
print(“\n— Data Selection and Filtering —“)
print(“Original df_sample:\n”, df_sample)
选择单个列 (Series)
name_column = df_sample[‘姓名’]
print(“\nSelecting ‘姓名’ column:\n”, name_column)
选择多个列 (DataFrame)
name_city_columns = df_sample[[‘姓名’, ‘城市’]]
print(“\nSelecting ‘姓名’ and ‘城市’ columns:\n”, name_city_columns)
“`
7.2 选择行 (基于索引和标签)
loc:基于标签(行索引和列名)选择。iloc:基于整数位置(行号和列号)选择。
“`python
使用 loc 选择行
选择第一行 (索引为0的行)
first_row_loc = df_sample.loc[0]
print(“\nSelecting first row using loc (index 0):\n”, first_row_loc)
选择指定索引的多行
multiple_rows_loc = df_sample.loc[[0, 2]]
print(“\nSelecting rows with index 0 and 2 using loc:\n”, multiple_rows_loc)
使用 iloc 选择行
选择第一行 (位置为0的行)
first_row_iloc = df_sample.iloc[0]
print(“\nSelecting first row using iloc (position 0):\n”, first_row_iloc)
选择指定位置的多行
multiple_rows_iloc = df_sample.iloc[[0, 2]]
print(“\nSelecting rows with position 0 and 2 using iloc:\n”, multiple_rows_iloc)
结合行和列选择
选择第一行的 ‘姓名’ 列
value_loc = df_sample.loc[0, ‘姓名’]
print(“\nSelecting ‘姓名’ from first row using loc:\n”, value_loc)
选择前两行的 ‘姓名’ 和 ‘年龄’ 列
subset_loc = df_sample.loc[0:1, [‘姓名’, ‘年龄’]]
print(“\nSelecting first two rows, ‘姓名’ and ‘年龄’ using loc:\n”, subset_loc)
选择所有行的第一列和第三列
subset_iloc = df_sample.iloc[:, [0, 2]]
print(“\nSelecting all rows, first and third column using iloc:\n”, subset_iloc)
“`
7.3 条件筛选
使用布尔条件筛选数据。
“`python
筛选年龄大于25的行
age_filter = df_sample[df_sample[‘年龄’] > 25]
print(“\nRows where Age > 25:\n”, age_filter)
筛选城市是 ‘北京’ 且年龄小于 30 的行
complex_filter = df_sample[(df_sample[‘城市’] == ‘北京’) & (df_sample[‘年龄’] < 30)]
print(“\nRows where City is ‘北京’ and Age < 30:\n”, complex_filter)
筛选城市在列表中的行
city_list_filter = df_sample[df_sample[‘城市’].isin([‘北京’, ‘深圳’])]
print(“\nRows where City is ‘北京’ or ‘深圳’:\n”, city_list_filter)
“`
8. 数据操作与转换
Pandas 提供了丰富的数据操作功能。
8.1 应用函数 (apply(), map())
apply():用于在DataFrame的行或列上应用函数。map():用于Series上的值到值的映射。
“`python
print(“\n— Data Manipulation —“)
假设我们想给每个人的年龄加一岁
df_manipulate = df_sample.copy()
df_manipulate[‘年龄_新’] = df_manipulate[‘年龄’].apply(lambda x: x + 1)
print(“\nAdding 1 to Age using apply:\n”, df_manipulate)
创建一个映射字典
city_map = {‘北京’: ‘Beijing’, ‘上海’: ‘Shanghai’, ‘广州’: ‘Guangzhou’, ‘深圳’: ‘Shenzhen’}
df_manipulate[‘城市_英文’] = df_manipulate[‘城市’].map(city_map)
print(“\nMapping Chinese cities to English using map:\n”, df_manipulate)
“`
8.2 数据排序 (sort_values())
“`python
按年龄升序排列
df_sorted_age = df_sample.sort_values(by=’年龄’)
print(“\nDataFrame sorted by Age (ascending):\n”, df_sorted_age)
按年龄降序排列
df_sorted_age_desc = df_sample.sort_values(by=’年龄’, ascending=False)
print(“\nDataFrame sorted by Age (descending):\n”, df_sorted_age_desc)
按多个列排序 (先按城市,再按年龄)
df_sorted_multi = df_sample.sort_values(by=[‘城市’, ‘年龄’])
print(“\nDataFrame sorted by City then Age:\n”, df_sorted_multi)
“`
8.3 数据分组与聚合 (groupby())
groupby() 是 Pandas 中非常强大的功能,用于根据一个或多个列的值将数据分成组,然后对每个组进行独立的计算。
“`python
data_group = {
‘部门’: [‘销售’, ‘市场’, ‘销售’, ‘技术’, ‘市场’, ‘技术’],
‘员工’: [‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’],
‘薪资’: [5000, 6000, 5500, 7000, 6200, 7500],
‘绩效’: [80, 90, 85, 95, 88, 92]
}
df_group = pd.DataFrame(data_group)
print(“\n— Grouping Data (groupby) —“)
print(“Original DataFrame for grouping:\n”, df_group)
按部门分组并计算平均薪资
avg_salary_by_dept = df_group.groupby(‘部门’)[‘薪资’].mean()
print(“\nAverage Salary by Department:\n”, avg_salary_by_dept)
按部门分组并计算多个聚合统计量
dept_summary = df_group.groupby(‘部门’).agg({
‘薪资’: [‘mean’, ‘min’, ‘max’],
‘绩效’: ‘mean’
})
print(“\nDepartment Summary (mean, min, max salary; mean performance):\n”, dept_summary)
“`
8.4 合并与连接 (merge(), concat())
concat():按轴(行或列)连接 DataFrame。merge():通过一个或多个键连接 DataFrame,类似于 SQL JOIN。
“`python
df1 = pd.DataFrame({‘key’: [‘K0’, ‘K1’, ‘K2’, ‘K3’], ‘A’: [‘A0’, ‘A1’, ‘A2’, ‘A3’]})
df2 = pd.DataFrame({‘key’: [‘K0’, ‘K1’, ‘K4’, ‘K5’], ‘B’: [‘B0’, ‘B1’, ‘B4’, ‘B5’]})
df3 = pd.DataFrame({‘A’: [‘A4’, ‘A5’], ‘B’: [‘B4’, ‘B5’]})
print(“\n— Merging and Concatenating DataFrames —“)
print(“df1:\n”, df1)
print(“df2:\n”, df2)
print(“df3:\n”, df3)
1. concat (按行连接)
df_concat_rows = pd.concat([df1, df3], ignore_index=True)
print(“\nConcatenated df1 and df3 (rows):\n”, df_concat_rows)
2. concat (按列连接)
df_concat_cols = pd.concat([df1, df2], axis=1) # 注意这里如果没有共同的索引,可能会有NaN
print(“\nConcatenated df1 and df2 (columns):\n”, df_concat_cols)
3. merge (内连接 – 默认)
df_merged_inner = pd.merge(df1, df2, on=’key’, how=’inner’)
print(“\nInner merge of df1 and df2 on ‘key’:\n”, df_merged_inner)
4. merge (左连接)
df_merged_left = pd.merge(df1, df2, on=’key’, how=’left’)
print(“\nLeft merge of df1 and df2 on ‘key’:\n”, df_merged_left)
5. merge (外连接)
df_merged_outer = pd.merge(df1, df2, on=’key’, how=’outer’)
print(“\nOuter merge of df1 and df2 on ‘key’:\n”, df_merged_outer)
“`
9. 简单数据分析与聚合
除了 groupby(),Pandas 还提供了一系列快捷的聚合函数。
“`python
print(“\n— Basic Data Analysis/Aggregation —“)
对数值列进行聚合操作
print(“\nMin Age:”, df_sample[‘年龄’].min())
print(“Max Age:”, df_sample[‘年龄’].max())
print(“Mean Age:”, df_sample[‘年龄’].mean())
print(“Sum of Ages:”, df_sample[‘年龄’].sum())
print(“Count of Ages:”, df_sample[‘年龄’].count())
计算城市列的唯一值及其计数
print(“\nValue counts for City:\n”, df_sample[‘城市’].value_counts())
“`
10. 结论与进阶
通过本教程,你已经掌握了 Python Pandas 进行数据清洗和分析的基础知识和常用操作。这包括:
- 理解
Series和DataFrame两种核心数据结构。 - 学会从不同文件格式导入和导出数据。
- 掌握数据初步探索的方法。
- 处理缺失值、重复值,以及数据类型转换和列重命名。
- 灵活进行数据选择、过滤、排序。
- 利用
apply()和map()进行数据转换。 - 使用
groupby()进行强大的数据分组与聚合。 - 理解
concat()和merge()的数据连接操作。 - 执行基础的统计聚合。
Pandas 的功能远不止于此,还有许多高级特性等待你去探索,例如:
- 时间序列分析:
resample()、shift()等。 - 窗口函数:
rolling()、expanding()等。 - 透视表 (Pivot Tables):
pivot_table()。 - 多级索引 (MultiIndex)。
- 结合 Matplotlib 和 Seaborn 进行数据可视化。
持续实践是掌握 Pandas 的关键。尝试在真实数据集上运用这些技能,你将很快成为一名高效的数据分析师!