Python 数据分析必学库:Pandas 详解
在当今数据驱动的世界中,Python 已经成为数据科学家和分析师的首选工具之一。而在 Python 丰富的数据生态系统中,Pandas 无疑是最核心、最强大的库之一。它为数据操作和分析提供了高效、灵活且易于使用的数据结构和功能,使得处理结构化数据变得前所未有的简单。
什么是 Pandas?
Pandas 是一个开源的 Python 库,主要用于数据分析和操作。它的核心是提供两种主要的数据结构:Series 和 DataFrame。这些结构旨在使处理关系型或带标签的数据变得直观,无论是处理表格数据(如 Excel 电子表格或 SQL 表)、时间序列数据,还是任意矩阵数据。
为什么选择 Pandas?
Pandas 之所以受到广泛欢迎,主要有以下几个原因:
- 高效的数据结构:
DataFrame类似于电子表格或 SQL 表,能够存储不同类型的数据,并支持各种复杂的数据操作。 - 数据清洗与预处理:提供强大的功能来处理缺失值、重复数据、数据类型转换等,是数据清洗阶段不可或缺的工具。
- 数据分析与探索:支持快速的数据聚合、分组、统计分析以及数据切片、筛选等操作,帮助用户迅速从数据中获取洞察。
- 与生态系统无缝集成:与
NumPy(数值计算)、Matplotlib和Seaborn(数据可视化)、Scikit-learn(机器学习)等其他流行的 Python 库无缝集成,构建完整的数据科学工作流。 - 丰富的数据读写能力:能够轻松读取和写入多种数据格式,如 CSV、Excel、JSON、SQL 数据库等。
安装 Pandas
安装 Pandas 非常简单,只需使用 Python 的包管理器 pip:
bash
pip install pandas
通常,我们也会同时安装 NumPy:
bash
pip install numpy
Pandas 核心数据结构
Pandas 提供了两个主要的数据结构,它们是所有数据操作的基础:
1. Series (序列)
Series 是一种一维带标签的数组,可以存储任何数据类型(整数、字符串、浮点数、Python 对象等)。它由两部分组成:数据和与之关联的标签(索引)。
“`python
import pandas as pd
从列表创建 Series
s = pd.Series([10, 20, 30, 40, 50])
print(“— Series from list —“)
print(s)
输出:
0 10
1 20
2 30
3 40
4 50
dtype: int64
可以自定义索引
s_indexed = pd.Series([100, 200, 300], index=[‘a’, ‘b’, ‘c’])
print(“\n— Series with custom index —“)
print(s_indexed)
输出:
a 100
b 200
c 300
dtype: int64
“`
2. DataFrame (数据框)
DataFrame 是 Pandas 中最常用的数据结构,它是一个二维的带标签的数据结构,可以看作是 Series 对象的字典(每一列都是一个 Series)。它拥有行索引(index)和列索引(columns),非常类似于电子表格或 SQL 表。
“`python
import pandas as pd
从字典创建 DataFrame
data = {
‘Name’: [‘Alice’, ‘Bob’, ‘Charlie’, ‘David’],
‘Age’: [25, 30, 35, 40],
‘City’: [‘New York’, ‘London’, ‘Paris’, ‘New York’]
}
df = pd.DataFrame(data)
print(“— DataFrame from dictionary —“)
print(df)
输出:
Name Age City
0 Alice 25 New York
1 Bob 30 London
2 Charlie 35 Paris
3 David 40 New York
“`
数据导入与导出
Pandas 提供了强大的功能来读写各种数据格式。
读取数据
“`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’)
从 SQL 数据库读取
from sqlalchemy import create_engine
engine = create_engine(‘sqlite:///mydatabase.db’) # 连接到 SQLite 数据库
df_sql = pd.read_sql(‘SELECT * FROM my_table’, engine)
“`
导出数据
“`python
导出为 CSV 文件 (index=False 不写入行索引)
df.to_csv(‘output.csv’, index=False)
导出为 Excel 文件
df.to_excel(‘output.xlsx’, index=False, sheet_name=’MyData’)
导出为 JSON 文件
df.to_json(‘output.json’, orient=’records’)
导出到 SQL 数据库
df.to_sql(‘new_table’, engine, if_exists=’replace’, index=False) # if_exists 可以是 ‘fail’, ‘replace’, ‘append’
“`
数据查看与基本信息
加载数据后,第一步通常是快速了解数据的概况。
“`python
查看前 N 行 (默认前 5 行)
print(“— df.head() —“)
print(df.head())
查看后 N 行 (默认后 5 行)
print(“\n— df.tail(2) —“)
print(df.tail(2))
获取 DataFrame 的简洁摘要,包括数据类型和非空值数量
print(“\n— df.info() —“)
df.info()
获取数值列的描述性统计信息 (均值、标准差、最大值、最小值等)
print(“\n— df.describe() —“)
print(df.describe())
获取 DataFrame 的维度 (行数, 列数)
print(“\n— df.shape —“)
print(df.shape)
获取列名
print(“\n— df.columns —“)
print(df.columns)
检查每列的缺失值数量
print(“\n— df.isnull().sum() —“)
print(df.isnull().sum())
“`
数据选择与索引
Pandas 提供了多种方法来选择数据,包括列选择、行选择以及基于标签和位置的复杂选择。
1. 选择列
“`python
选择单列 (返回 Series)
names = df[‘Name’]
print(“\n— Selecting ‘Name’ column —“)
print(names)
选择多列 (返回 DataFrame)
subset = df[[‘Name’, ‘Age’]]
print(“\n— Selecting ‘Name’ and ‘Age’ columns —“)
print(subset)
“`
2. 选择行
使用布尔索引进行条件筛选:
“`python
筛选年龄大于 30 的行
old_people = df[df[‘Age’] > 30]
print(“\n— Filtering by Age > 30 —“)
print(old_people)
筛选城市是 ‘New York’ 的行
ny_residents = df[df[‘City’] == ‘New York’]
print(“\n— Filtering by City == ‘New York’ —“)
print(ny_residents)
组合条件筛选
combined_filter = df[(df[‘Age’] > 30) & (df[‘City’] == ‘New York’)]
print(“\n— Filtering by Age > 30 AND City == ‘New York’ —“)
print(combined_filter)
“`
3. 使用 .loc[] (基于标签的索引)
.loc[] 主要用于通过行和列的标签(名称)进行选择。
“`python
选择特定行和列的值 (行索引为 0, 列名为 ‘Name’)
print(“\n— df.loc[0, ‘Name’] —“)
print(df.loc[0, ‘Name’])
选择所有行和特定列
print(“\n— df.loc[:, [‘Name’, ‘City’]] —“)
print(df.loc[:, [‘Name’, ‘City’]])
结合条件筛选
print(“\n— Conditional selection with .loc (Age > 30) —“)
print(df.loc[df[‘Age’] > 30, [‘Name’, ‘City’]])
“`
4. 使用 .iloc[] (基于位置的索引)
.iloc[] 主要用于通过行和列的整数位置(从 0 开始)进行选择。
“`python
选择第一行和第一列的值
print(“\n— df.iloc[0, 0] —“)
print(df.iloc[0, 0])
选择前两行和所有列
print(“\n— df.iloc[0:2, :] —“)
print(df.iloc[0:2, :])
选择所有行和前两列
print(“\n— df.iloc[:, 0:2] —“)
print(df.iloc[:, 0:2])
“`
数据清洗与预处理
数据清洗是数据分析的关键步骤。Pandas 提供了各种工具来处理数据中的常见问题。
1. 处理缺失值
“`python
import numpy as np
df_missing = pd.DataFrame({
‘A’: [1, 2, np.nan, 4],
‘B’: [5, np.nan, 7, 8],
‘C’: [9, 10, 11, 12]
})
print(“— Original DataFrame with missing values —“)
print(df_missing)
填充缺失值 (例如,用 0 填充)
df_filled = df_missing.fillna(0)
print(“\n— DataFrame after fillna(0) —“)
print(df_filled)
用列的均值填充缺失值
df_mean_filled = df_missing.fillna(df_missing[‘A’].mean())
print(“\n— DataFrame after filling with column mean —“)
print(df_mean_filled)
删除含有任何缺失值的行
df_dropna_row = df_missing.dropna()
print(“\n— DataFrame after dropna() (rows) —“)
print(df_dropna_row)
删除含有所有缺失值的列
df_dropna_col = df_missing.dropna(axis=1, how=’all’)
print(“\n— DataFrame after dropna(axis=1, how=’all’) (columns) —“)
print(df_dropna_col)
“`
2. 删除重复值
“`python
df_duplicates = pd.DataFrame({
‘col1’: [1, 2, 2, 3],
‘col2’: [‘A’, ‘B’, ‘B’, ‘C’]
})
print(“— Original DataFrame with duplicates —“)
print(df_duplicates)
删除所有重复的行
df_unique = df_duplicates.drop_duplicates()
print(“\n— DataFrame after drop_duplicates() —“)
print(df_unique)
删除特定列上的重复项 (例如,只考虑 ‘col1’)
df_unique_col1 = df_duplicates.drop_duplicates(subset=[‘col1’])
print(“\n— DataFrame after drop_duplicates(subset=[‘col1’]) —“)
print(df_unique_col1)
“`
3. 改变数据类型
“`python
df_types = pd.DataFrame({‘col1’: [‘1’, ‘2’, ‘3’], ‘col2’: [‘4.5’, ‘5.6’, ‘6.7’]})
print(“— Original DataFrame types —“)
df_types.info()
将 ‘col1’ 转换为整数类型
df_types[‘col1’] = df_types[‘col1’].astype(int)
将 ‘col2’ 转换为浮点数类型
df_types[‘col2’] = df_types[‘col2’].astype(float)
print(“\n— DataFrame types after conversion —“)
df_types.info()
“`
数据操作
1. 排序数据
“`python
print(“— Original DataFrame —“)
print(df)
按 ‘Age’ 列升序排序
df_sorted_age = df.sort_values(by=’Age’)
print(“\n— Sorted by Age (ascending) —“)
print(df_sorted_age)
按 ‘Age’ 列降序排序,并按 ‘City’ 列升序排序
df_sorted_multi = df.sort_values(by=[‘Age’, ‘City’], ascending=[False, True])
print(“\n— Sorted by Age (descending) then City (ascending) —“)
print(df_sorted_multi)
“`
2. 添加/修改列
“`python
添加新列
df[‘Salary’] = [50000, 60000, 75000, 80000]
print(“\n— DataFrame after adding ‘Salary’ column —“)
print(df)
修改现有列
df[‘Age’] = df[‘Age’] + 1
print(“\n— DataFrame after modifying ‘Age’ column —“)
print(df)
“`
3. 应用函数 (.apply(), .map())
apply() 可以将函数应用到 Series 或 DataFrame 的行/列。map() 主要用于 Series 上的元素级映射。
“`python
对 ‘Name’ 列应用 len() 函数
df[‘Name_Length’] = df[‘Name’].apply(len)
print(“\n— DataFrame with ‘Name_Length’ —“)
print(df)
使用 lambda 函数创建新列 (基于行数据)
df[‘Age_Category’] = df.apply(lambda row: ‘Adult’ if row[‘Age’] >= 30 else ‘Young’, axis=1)
print(“\n— DataFrame with ‘Age_Category’ —“)
print(df)
使用 .map() 替换 ‘City’ 列的值
city_mapping = {‘New York’: ‘NY’, ‘London’: ‘LDN’, ‘Paris’: ‘PRS’}
df[‘City_Abbr’] = df[‘City’].map(city_mapping)
print(“\n— DataFrame with ‘City_Abbr’ —“)
print(df)
“`
数据聚合与分组
groupby() 是 Pandas 中最强大的功能之一,它允许你根据一个或多个键对 DataFrame 进行分组,然后对每个组独立地执行聚合操作。
“`python
print(“— Original DataFrame —“)
print(df)
按 ‘City’ 分组,并计算每个城市的平均年龄和最大年龄
avg_age_by_city = df.groupby(‘City’)[‘Age’].mean()
print(“\n— Average Age by City —“)
print(avg_age_by_city)
使用 .agg() 进行多重聚合
city_stats = df.groupby(‘City’).agg(
Avg_Age=(‘Age’, ‘mean’),
Max_Age=(‘Age’, ‘max’),
Count_People=(‘Name’, ‘count’)
)
print(“\n— City Statistics using .agg() —“)
print(city_stats)
计算每个城市的人数
print(“\n— Value Counts for City —“)
print(df[‘City’].value_counts())
“`
合并 DataFrame
Pandas 提供了多种方法来组合 DataFrame,类似于 SQL 中的 JOIN 操作。
1. pd.concat() (连接)
pd.concat() 用于沿着某个轴堆叠或连接 DataFrame。
“`python
df1 = pd.DataFrame({‘A’: [‘A0’, ‘A1’], ‘B’: [‘B0’, ‘B1’]})
df2 = pd.DataFrame({‘A’: [‘A2’, ‘A3’], ‘B’: [‘B2’, ‘B3’]})
垂直堆叠 (默认 axis=0)
combined_vertical = pd.concat([df1, df2])
print(“— Vertical Concatenation —“)
print(combined_vertical)
水平连接 (axis=1)
combined_horizontal = pd.concat([df1, df2], axis=1)
print(“\n— Horizontal Concatenation —“)
print(combined_horizontal)
“`
2. pd.merge() (合并)
pd.merge() 类似于数据库的 JOIN 操作,根据一个或多个键列连接 DataFrame。
“`python
df_left = pd.DataFrame({‘key’: [‘K0’, ‘K1’, ‘K2’, ‘K3’],
‘value_left’: [‘L0’, ‘L1’, ‘L2’, ‘L3’]})
df_right = pd.DataFrame({‘key’: [‘K0’, ‘K1’, ‘K4’, ‘K5’],
‘value_right’: [‘R0’, ‘R1’, ‘R4’, ‘R5’]})
print(“— df_left —“)
print(df_left)
print(“\n— df_right —“)
print(df_right)
内连接 (inner join): 只保留两个 DataFrame 中 key 都存在的行
merged_inner = pd.merge(df_left, df_right, on=’key’, how=’inner’)
print(“\n— Inner Merge —“)
print(merged_inner)
左连接 (left join): 保留左边所有行,右边匹配的行,不匹配的填充 NaN
merged_left = pd.merge(df_left, df_right, on=’key’, how=’left’)
print(“\n— Left Merge —“)
print(merged_left)
右连接 (right join): 保留右边所有行,左边匹配的行,不匹配的填充 NaN
merged_right = pd.merge(df_left, df_right, on=’key’, how=’right’)
print(“\n— Right Merge —“)
print(merged_right)
外连接 (outer join): 保留所有行,不匹配的填充 NaN
merged_outer = pd.merge(df_left, df_right, on=’key’, how=’outer’)
print(“\n— Outer Merge —“)
print(merged_outer)
“`
结语
Pandas 是 Python 数据分析领域的一把瑞士军刀。通过本文的详细介绍,你应该对 Pandas 的核心数据结构、数据导入导出、查看与索引、数据清洗、操作以及聚合合并等关键功能有了全面的理解。掌握 Pandas 是成为一名高效数据分析师或数据科学家的基石。
建议你亲自动手实践这些代码示例,并尝试解决实际的数据问题。随着经验的积累,你会发现 Pandas 的强大之处远不止于此,它将极大地提升你的数据处理效率和能力。