Pandas 实用教程:数据分析师必备技能
对于任何一位数据分析师而言,Pandas 都是一个绕不开的核心工具。它强大、灵活、高效,可以处理各种类型的数据,并进行清洗、转换、分析和可视化。毫不夸张地说,熟练掌握 Pandas 是数据分析师的必备技能之一。
本文将深入探讨 Pandas 的核心功能,并通过大量实例演示其在实际工作中的应用。无论你是 Pandas 新手,还是希望进一步提升技能的数据分析师,相信都能从本文中获益。
一、Pandas 简介:数据分析的瑞士军刀
Pandas 是 Python 的一个开源数据分析库,建立在 NumPy 之上,提供了高性能、易于使用的数据结构和数据分析工具。它的名字来源于 “Panel Data”(面板数据)和 “Python Data Analysis”(Python 数据分析)的结合。
Pandas 主要提供两种数据结构:
- Series:类似于一维数组,但可以拥有自定义的索引(标签),而不仅仅是整数索引。
- DataFrame:类似于二维表格,由多个 Series 组成,每个 Series 构成一列。DataFrame 既有行索引也有列索引。
Pandas 之所以如此受欢迎,主要得益于以下几个方面:
- 数据处理能力强大:Pandas 可以处理各种数据类型(数值、文本、日期时间等),并提供丰富的数据清洗、转换、合并、重塑等功能。
- 易于使用:Pandas 的 API 设计简洁直观,学习曲线相对平缓。
- 与其他库集成良好:Pandas 可以与 NumPy、Scikit-learn、Matplotlib、Seaborn 等 Python 数据科学生态系统中的其他库无缝集成,构建强大的数据分析工作流。
- 社区活跃:Pandas 拥有庞大而活跃的社区,遇到问题可以很容易地找到帮助。
二、Pandas 核心功能详解
1. 数据读取与写入
Pandas 支持读取和写入多种格式的数据,包括:
- CSV、TSV
- Excel
- JSON
- HTML
- SQL 数据库
- HDF5
- Parquet
- Feather
- …
读取 CSV 文件:
“`python
import pandas as pd
读取 CSV 文件,自动推断数据类型
df = pd.read_csv(‘data.csv’)
指定分隔符、编码、表头等参数
df = pd.read_csv(‘data.tsv’, sep=’\t’, encoding=’utf-8′, header=0)
读取部分列
df = pd.read_csv(‘data.csv’, usecols=[‘col1’, ‘col2’])
跳过行
df = pd.read_csv(‘data.csv’, skiprows=2)
“`
读取 Excel 文件:
“`python
读取第一个工作表
df = pd.read_excel(‘data.xlsx’)
读取指定工作表
df = pd.read_excel(‘data.xlsx’, sheet_name=’Sheet2′)
指定表头行、索引列等
df = pd.read_excel(‘data.xlsx’, header=1, index_col=0)
“`
写入 CSV 文件:
“`python
将 DataFrame 写入 CSV 文件
df.to_csv(‘output.csv’, index=False) # 不写入行索引
指定分隔符、编码等
df.to_csv(‘output.tsv’, sep=’\t’, encoding=’utf-8′)
“`
写入 Excel 文件:
“`python
将 DataFrame 写入 Excel 文件
df.to_excel(‘output.xlsx’, sheet_name=’Sheet1′, index=False)
“`
2. 数据查看与探索
读取数据后,我们需要对数据进行初步的查看和探索,了解数据的基本情况。
查看头部/尾部数据:
“`python
查看前 5 行
df.head()
查看前 10 行
df.head(10)
查看最后 5 行
df.tail()
“`
查看数据形状:
“`python
返回 (行数, 列数) 的元组
df.shape
“`
查看列名:
python
df.columns
查看数据类型:
python
df.dtypes
查看数据信息:
“`python
显示索引、列、数据类型、非空值数量、内存占用等信息
df.info()
“`
查看数值型列的统计信息:
“`python
显示计数、均值、标准差、最小值、25% 分位数、中位数、75% 分位数、最大值
df.describe()
“`
查看非数值型列的统计信息:
“`python
显示计数、唯一值数量、出现频率最高的值、最高频次
df.describe(include=[‘object’]) # 或者 include=[‘category’]
“`
查看唯一值:
“`python
查看某一列的唯一值
df[‘column_name’].unique()
查看唯一值数量
df[‘column_name’].nunique()
“`
查看值计数:
“`python
查看某一列每个值的出现次数
df[‘column_name’].value_counts()
“`
3. 数据选择与过滤
Pandas 提供了多种方式来选择和过滤数据。
选择列:
“`python
选择单列,返回 Series
df[‘column_name’]
df.column_name # 当列名是有效的 Python 标识符时可以使用
选择多列,返回 DataFrame
df[[‘column1’, ‘column2’]]
“`
选择行:
“`python
通过行索引选择,loc 基于标签
df.loc[0] # 选择索引为 0 的行
df.loc[0:2] # 选择索引为 0、1、2 的行(包含 2)
df.loc[[0, 2, 4]] # 选择索引为 0、2、4 的行
通过行号选择,iloc 基于位置
df.iloc[0] # 选择第 1 行
df.iloc[0:2] # 选择第 1、2 行(不包含 2)
df.iloc[[0, 2, 4]] # 选择第 1、3、5 行
“`
同时选择行和列:
“`python
loc 基于标签
df.loc[0:2, [‘column1’, ‘column2’]]
iloc 基于位置
df.iloc[0:2, 0:2]
“`
条件过滤:
“`python
选择 column1 大于 10 的行
df[df[‘column1’] > 10]
选择 column1 大于 10 且 column2 等于 ‘A’ 的行
df[(df[‘column1’] > 10) & (df[‘column2’] == ‘A’)]
选择 column1 大于 10 或 column2 等于 ‘B’ 的行
df[(df[‘column1’] > 10) | (df[‘column2’] == ‘B’)]
使用 isin() 方法
df[df[‘column1’].isin([1, 2, 3])]
使用 query() 方法(字符串表达式)
df.query(‘column1 > 10 and column2 == “A”‘)
“`
4. 数据清洗
数据清洗是数据分析中至关重要的一步,Pandas 提供了丰富的函数来处理缺失值、重复值、异常值等。
处理缺失值:
“`python
检测缺失值
df.isnull() # 返回布尔型 DataFrame,缺失值为 True
df.isna() # 与 isnull() 等价
df.isnull().sum() # 统计每列缺失值数量
删除缺失值
df.dropna() # 删除包含缺失值的行
df.dropna(axis=1) # 删除包含缺失值的列
df.dropna(subset=[‘column1’, ‘column2’]) # 删除指定列包含缺失值的行
df.dropna(thresh=2) # 保留至少有 2 个非缺失值的行
填充缺失值
df.fillna(0) # 用 0 填充所有缺失值
df[‘column1’].fillna(df[‘column1′].mean()) # 用均值填充
df.fillna(method=’ffill’) # 用前一个非缺失值填充 (forward fill)
df.fillna(method=’bfill’) # 用后一个非缺失值填充 (backward fill)
“`
处理重复值:
“`python
检测重复值
df.duplicated() # 返回布尔型 Series,重复行为 True
df.duplicated().sum() # 统计重复行数量
删除重复值
df.drop_duplicates() # 删除所有列都相同的重复行
df.drop_duplicates(subset=[‘column1’, ‘column2′]) # 删除指定列相同的重复行
df.drop_duplicates(keep=’first’) # 保留第一次出现的重复行(默认)
df.drop_duplicates(keep=’last’) # 保留最后一次出现的重复行
df.drop_duplicates(keep=False) # 删除所有重复行
“`
处理异常值:
Pandas 本身没有直接的异常值处理函数,但可以结合条件过滤、统计方法等来识别和处理异常值。
“`python
例如,删除 column1 中大于 3 倍标准差的值
df = df[df[‘column1’] <= df[‘column1’].mean() + 3 * df[‘column1’].std()]
“`
5. 数据转换
数据转换是将数据从一种形式转换为另一种形式的过程。
数据类型转换:
“`python
将列转换为数值型
df[‘column1’] = df[‘column1’].astype(int)
df[‘column1’] = df[‘column1’].astype(float)
将列转换为字符串型
df[‘column2’] = df[‘column2’].astype(str)
将列转换为日期时间型
df[‘date_column’] = pd.to_datetime(df[‘date_column’])
“`
应用函数:
“`python
对单列应用函数
df[‘column1’].apply(lambda x: x * 2)
对多列应用函数
df[[‘column1’, ‘column2’]].apply(lambda x: x.max() – x.min(), axis=1)
对整个 DataFrame 应用函数
df.applymap(lambda x: x * 2 if isinstance(x, (int, float)) else x)
“`
字符串处理:
Pandas 的 Series 对象提供了丰富的字符串处理方法(通过 .str
访问器)。
“`python
转换为小写
df[‘column2’].str.lower()
转换为大写
df[‘column2’].str.upper()
提取子字符串
df[‘column2’].str.slice(0, 3)
替换字符串
df[‘column2’].str.replace(‘old’, ‘new’)
包含子字符串
df[‘column2’].str.contains(‘substring’)
拆分字符串
df[‘column2’].str.split(‘,’)
更多字符串方法…
“`
日期时间处理:
Pandas 的日期时间类型(datetime64
)提供了强大的日期时间处理功能。
“`python
提取年、月、日、时、分、秒等
df[‘date_column’].dt.year
df[‘date_column’].dt.month
df[‘date_column’].dt.day
df[‘date_column’].dt.hour
df[‘date_column’].dt.minute
df[‘date_column’].dt.second
计算时间差
df[‘time_diff’] = df[‘date_column2’] – df[‘date_column1’]
df[‘time_diff’].dt.days # 提取天数
日期时间运算
df[‘new_date’] = df[‘date_column’] + pd.DateOffset(days=1)
更多日期时间方法…
“`
6. 数据分组与聚合
分组与聚合是数据分析中常用的操作,用于对数据进行分组并计算汇总统计信息。
“`python
按照 column1 分组,计算 column2 的均值
df.groupby(‘column1’)[‘column2’].mean()
按照 column1 分组,计算 column2 的多个统计量
df.groupby(‘column1’)[‘column2’].agg([‘mean’, ‘sum’, ‘count’])
按照多个列分组
df.groupby([‘column1’, ‘column2’])[‘column3’].mean()
对不同的列应用不同的聚合函数
df.groupby(‘column1’).agg({‘column2’: ‘mean’, ‘column3’: ‘sum’})
使用自定义聚合函数
def weighted_average(x):
return (x * df.loc[x.index, ‘weights’]).sum() / df.loc[x.index, ‘weights’].sum()
df.groupby(‘column1’)[‘column2’].agg(weighted_average)
“`
7. 数据合并与连接
Pandas 提供了多种方式来合并和连接多个 DataFrame。
concat()
函数:
“`python
沿行方向(垂直)堆叠
pd.concat([df1, df2])
沿列方向(水平)堆叠
pd.concat([df1, df2], axis=1)
指定连接方式(inner、outer)
pd.concat([df1, df2], axis=1, join=’inner’) # 只保留共有的索引
“`
merge()
函数:
“`python
基于单列进行连接
pd.merge(df1, df2, on=’key_column’)
基于多列进行连接
pd.merge(df1, df2, on=[‘key1’, ‘key2’])
指定连接方式(left、right、outer、inner)
pd.merge(df1, df2, on=’key_column’, how=’left’) # 左连接
指定左右 DataFrame 的连接列
pd.merge(df1, df2, left_on=’left_key’, right_on=’right_key’)
“`
join()
方法:
join()
方法主要用于基于索引的连接,是 merge()
的一种简化形式。
“`python
基于索引连接
df1.join(df2, how=’left’)
“`
8. 数据重塑
数据重塑是改变数据的行列结构,使其更适合分析。
pivot()
函数:
pivot()
函数用于将“长”数据转换为“宽”数据。
“`python
将 df 转换为以 column1 为索引,column2 为列,column3 为值的新 DataFrame
df.pivot(index=’column1′, columns=’column2′, values=’column3′)
“`
melt()
函数:
melt()
函数是 pivot()
的逆操作,将“宽”数据转换为“长”数据。
“`python
将 df 转换为以 column1 和新生成的 variable 列为标识,value 列为值的长格式 DataFrame
df.melt(id_vars=’column1′, value_vars=[‘column2’, ‘column3’])
“`
stack()
和 unstack()
方法:
stack()
将列索引转换为行索引(多层索引),unstack()
将行索引转换为列索引。
“`python
将 DataFrame 的列索引堆叠到行索引
df.stack()
将多层索引 DataFrame 的内层行索引拆堆到列索引
df.unstack()
“`
9. 数据排序
“`python
按值排序
df.sort_values(by=’column1′) # 升序
df.sort_values(by=’column1′, ascending=False) # 降序
df.sort_values(by=[‘column1’, ‘column2’]) # 先按 column1 排序,再按 column2 排序
按索引排序
df.sort_index() # 升序
df.sort_index(ascending=False) # 降序
“`
10. 数据透视表
Pandas 提供了 pivot_table()
函数来创建数据透视表,这是一种强大的数据汇总工具。
“`python
创建数据透视表,以 column1 为行索引,column2 为列索引,计算 column3 的均值
pd.pivot_table(df, index=’column1′, columns=’column2′, values=’column3′, aggfunc=’mean’)
使用多个聚合函数
pd.pivot_table(df, index=’column1′, columns=’column2′, values=’column3′, aggfunc=[‘mean’, ‘sum’])
添加行/列小计
pd.pivot_table(df, index=’column1′, columns=’column2′, values=’column3′, aggfunc=’mean’, margins=True)
“`
三、Pandas 进阶技巧
1. 多层索引 (MultiIndex)
多层索引允许你在 DataFrame 的行或列上拥有多个层级的索引,这在处理复杂的数据结构时非常有用。
“`python
创建多层索引 DataFrame
arrays = [[‘A’, ‘A’, ‘B’, ‘B’], [1, 2, 1, 2]]
index = pd.MultiIndex.from_arrays(arrays, names=(‘letter’, ‘number’))
df = pd.DataFrame({‘data’: [10, 20, 30, 40]}, index=index)
选择多层索引数据
df.loc[(‘A’, 1)] # 选择第一层为 ‘A’,第二层为 1 的数据
df.loc[‘A’] # 选择第一层为 ‘A’ 的所有数据
使用切片
df.loc[(slice(None), [1, 2]), :] # 选择第二层为 1 或 2 的所有数据
“`
2. 窗口函数
窗口函数允许你对数据进行滚动或扩展窗口的计算,例如计算移动平均、滚动求和等。
“`python
计算 3 期移动平均
df[‘column1’].rolling(window=3).mean()
计算累计求和
df[‘column1’].expanding().sum()
计算指数加权移动平均
df[‘column1’].ewm(span=3).mean()
“`
3. 性能优化
对于大型数据集,Pandas 的性能优化非常重要。以下是一些常用的优化技巧:
- 向量化操作:尽量使用 Pandas 内置的向量化操作,避免使用循环。
- 选择合适的数据类型:使用更小的数据类型(例如
int32
代替int64
)可以减少内存占用。 - 使用
.loc
和.iloc
:在进行数据选择时,尽量使用.loc
和.iloc
,它们比直接使用[]
更高效。 - 使用
category
类型:对于具有少量唯一值的字符串列,使用category
类型可以显著提高性能和减少内存占用。 - 分块处理:对于非常大的数据集,可以分块读取和处理数据。
- 使用
.eval()
和.query()
: 这两个函数内部使用numexpr 来进行加速运算。
四、总结
Pandas 是数据分析师的强大工具,提供了丰富的数据处理、分析和可视化功能。本文详细介绍了 Pandas 的核心功能和一些进阶技巧,并通过大量实例演示了其在实际工作中的应用。
当然,Pandas 的功能远不止于此。要成为一名 Pandas 高手,还需要不断学习、实践和探索。希望本文能为你提供一个良好的起点,帮助你更好地掌握 Pandas,并在数据分析的道路上更进一步。