Pandas 入门指南:数据分析的得力助手
在当今数据驱动的世界里,有效地处理、分析和理解数据是许多领域的核心技能。无论你是数据科学家、数据分析师、工程师,还是对数据感兴趣的学生,掌握强大的数据处理工具都至关重要。在 Python 的生态系统中,Pandas 库无疑是数据处理和分析领域的王者。
Pandas 提供了一套快速、灵活且富有表现力的数据结构,旨在让使用“关系型”或“带标签的”数据变得简单直观。它是构建在 NumPy 库之上,并在数据清洗、转换、合并、切片、聚合等方面提供了丰富的功能。本文将带你从零开始,逐步认识和使用 Pandas 这个强大的工具。
我们将涵盖以下内容:
- Pandas 是什么?为什么选择 Pandas?
- 安装 Pandas
- Pandas 的核心数据结构:Series 和 DataFrame
- 理解 Series
- 理解 DataFrame
- 创建 Series 和 DataFrame
- 从列表/NumPy 数组创建
- 从字典创建
- 从文件读取数据 (CSV, Excel)
- 查看数据
.head()
,.tail()
,.info()
,.describe()
,.shape
- 数据选择与索引
- 列选择
- 行选择 (
.loc
和.iloc
的区别与使用) - 布尔索引 (条件筛选)
- 基本数据操作
- 添加、删除、修改列
- 重命名列和索引
- 处理缺失数据 (
.isnull()
,.notnull()
,.dropna()
,.fillna()
) - 数据类型转换 (
.astype()
)
- 数据排序
- 按值排序 (
.sort_values()
) - 按索引排序 (
.sort_index()
)
- 按值排序 (
- 数据分组与聚合 (
.groupby()
) - 数据合并 (
.merge()
) - 数据输出
- 保存到文件 (CSV, Excel)
- 总结与展望
1. Pandas 是什么?为什么选择 Pandas?
Pandas 是什么?
Pandas 是一个开源的 Python 库,专注于提供高性能、易于使用的数据结构和数据分析工具。它的名字来源于 “Panel Data”(面板数据)和 “Python Data Analysis”(Python 数据分析)。
为什么选择 Pandas?
- 强大的数据结构: Pandas 引入了
Series
和DataFrame
,它们是处理各种类型数据的理想工具,尤其适用于表格数据(如数据库表、电子表格)。 - 数据清洗与准备: 现实世界的数据往往是混乱、不完整或格式不统一的。Pandas 提供了丰富的功能来处理缺失值、异常值、重复项,进行数据转换、格式化等,极大地简化了数据清洗过程。
- 数据探索与分析: 可以轻松地进行数据切片、切块、聚合、分组、合并、连接等操作,快速获得数据的概览、统计信息和洞察。
- 灵活的输入输出: 支持从多种文件格式读取数据(CSV, Excel, SQL 数据库, JSON, HDF5 等)并将处理后的数据输出到这些格式。
- 集成性好: 与 Python 生态系统中的其他库(如 NumPy, Matplotlib, Scikit-learn)紧密集成,方便进行科学计算、数据可视化和机器学习。
- 性能高效: 底层使用 NumPy 实现,处理大量数据时性能通常比较出色。
总而言之,如果你需要在 Python 中进行数据加载、清洗、转换、分析和可视化准备,Pandas 是你的首选工具。
2. 安装 Pandas
安装 Pandas 非常简单。如果你已经安装了 Python 和包管理器 pip,可以通过命令行执行:
bash
pip install pandas
如果你使用的是 Anaconda 发行版,Pandas 通常已经预装好了。如果需要更新或确保安装,可以使用 conda:
bash
conda install pandas
安装完成后,在 Python 脚本或交互式环境中,通常会按照约定俗成的惯例将其导入为 pd
:
python
import pandas as pd
import numpy as np # Pandas 很多功能依赖 NumPy,通常也一起导入
接下来,我们将深入了解 Pandas 的核心。
3. Pandas 的核心数据结构:Series 和 DataFrame
Pandas 的核心是其两种主要的数据结构:Series 和 DataFrame。理解它们是掌握 Pandas 的关键。
理解 Series
Series
可以被看作是一种带有标签的一维数组。它类似于 NumPy 的一维数组,但额外提供了索引(label),使得可以通过标签来访问数据。
- 数据 (Values): Series 包含一组数据,可以是任意的数据类型(整数、浮点数、字符串、Python 对象等)。
- 索引 (Index): Series 包含一个与之关联的索引,为每个数据点提供一个标签。如果没有显式指定索引,Pandas 会自动创建一个从 0 开始的默认整数索引。
你可以想象 Series 就像电子表格中的一列数据,其中索引是行号或行标签。
示例:
“`python
import pandas as pd
创建一个简单的 Series
s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(s)
“`
输出解释:
0 1.0
1 3.0
2 5.0
3 NaN
4 6.0
5 8.0
dtype: float64
左边的数字(0, 1, 2, 3, 4, 5)是默认的索引。右边是对应的数据值。np.nan
表示缺失值。dtype: float64
表示 Series 中数据的数据类型。
你可以通过索引访问 Series 中的元素:
python
print(s[0]) # 访问索引为 0 的元素
print(s[:3]) # 访问前三个元素 (切片)
你也可以创建带有自定义索引的 Series:
python
s2 = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
print(s2)
print(s2['b']) # 通过自定义索引访问
输出解释:
“`
a 10
b 20
c 30
d 40
dtype: int64
20 # 通过自定义索引访问 ‘b’ 对应的值
“`
理解 DataFrame
DataFrame
是 Pandas 中最重要也是最常用的数据结构。它可以被看作是一个二维的、大小可变的、带有标签的表格数据结构,类似于关系型数据库中的表或电子表格。
- 数据 (Data): DataFrame 包含按行和列组织的二维数据。
- 列 (Columns): 每一列都有一个标签(列名),并且每一列本质上都是一个 Series,共享同一个索引。
- 索引 (Index): DataFrame 有一个行索引,为每一行提供一个标签。同样,如果没有显式指定,会使用从 0 开始的默认整数索引。
你可以将 DataFrame 想象成一个完整的电子表格或数据库表,其中列是不同的字段,行是不同的记录,行索引是记录的唯一标识。
示例:
“`python
import pandas as pd
import numpy as np
创建一个简单的 DataFrame
data = {‘col1’: [1, 2, 3, 4],
‘col2’: [‘A’, ‘B’, ‘C’, ‘D’],
‘col3’: [True, False, True, False]}
df = pd.DataFrame(data)
print(df)
“`
输出解释:
col1 col2 col3
0 1 A True
1 2 B False
2 3 C True
3 4 D False
左边的数字(0, 1, 2, 3)是行索引,顶部的 ‘col1’, ‘col2’, ‘col3’ 是列名。
DataFrame 的强大之处在于它可以容纳不同数据类型的列(因为每列是一个 Series),并且提供了丰富的行和列操作功能。
你可以访问 DataFrame 的列:
python
print(df['col1']) # 访问 'col1' 列,结果是一个 Series
print(type(df['col1']))
你也可以访问 DataFrame 的行(后面会详细介绍使用 .loc
和 .iloc
)。
4. 创建 Series 和 DataFrame
了解了核心结构后,我们看看如何创建它们。
从列表/NumPy 数组创建
“`python
创建 Series
s = pd.Series([10, 20, 30])
print(s)
从 NumPy 数组创建 DataFrame
arr = np.random.randn(6, 4) # 创建一个 6×4 的随机数组
dates = pd.date_range(‘20230101’, periods=6) # 创建一个日期索引
df = pd.DataFrame(arr, index=dates, columns=list(‘ABCD’)) # 指定索引和列名
print(df)
“`
从字典创建
字典是创建 Series 和 DataFrame 的常用方式。
“`python
从字典创建 Series (字典的键成为索引)
d = {‘a’: 100, ‘b’: 200, ‘c’: 300}
s3 = pd.Series(d)
print(s3)
从字典创建 DataFrame (字典的键成为列名)
data = {‘col1’: [1, 2, 3], ‘col2’: [‘X’, ‘Y’, ‘Z’]}
df2 = pd.DataFrame(data)
print(df2)
如果字典的值是 Series,可以创建对齐索引的 DataFrame
d2 = {‘col_A’: pd.Series([1, 2, 3], index=[‘x’, ‘y’, ‘z’]),
‘col_B’: pd.Series([4, 5, 6, 7], index=[‘x’, ‘y’, ‘z’, ‘w’])}
df3 = pd.DataFrame(d2) # 会自动对齐索引,没有对应值的会是 NaN
print(df3)
“`
从文件读取数据 (CSV, Excel)
这是实际应用中最常见的创建 DataFrame 的方式。Pandas 提供了 read_csv()
和 read_excel()
等函数。
“`python
假设有一个名为 ‘data.csv’ 的文件
内容可能类似:
id,name,age
1,Alice,30
2,Bob,25
3,Charlie,35
读取 CSV 文件
try:
df_csv = pd.read_csv(‘data.csv’) # 请替换为你的文件路径
print(“\n— 从 CSV 读取的数据 —“)
print(df_csv)
except FileNotFoundError:
print(“\n错误:data.csv 文件未找到。跳过 CSV 读取示例。”)
# 创建一个模拟的 DataFrame 用于后续操作
data_mock = {‘id’: [1, 2, 3, 4, 5],
‘name’: [‘Alice’, ‘Bob’, ‘Charlie’, ‘David’, ‘Eva’],
‘age’: [30, 25, 35, 40, 28],
‘city’: [‘New York’, ‘Los Angeles’, ‘Chicago’, ‘New York’, ‘Los Angeles’],
‘score’: [85.5, 90.2, 78.9, np.nan, 92.1]}
df_csv = pd.DataFrame(data_mock)
假设有一个名为 ‘data.xlsx’ 的文件
读取 Excel 文件 (需要安装 openpyxl 或 xlrd 库:pip install openpyxl)
try:
df_excel = pd.read_excel(‘data.xlsx’) # 请替换为你的文件路径
print(“\n— 从 Excel 读取的数据 —“)
print(df_excel)
except FileNotFoundError:
print(“\n错误:data.xlsx 文件未找到。跳过 Excel 读取示例。”)
except ImportError:
print(“\n错误:读取 Excel 需要安装 openpyxl 或 xlrd。跳过 Excel 读取示例。”)
为了演示,我们使用模拟创建的 df_csv 作为后续的示例数据框 df
df = df_csv.copy()
print(“\n— 用于后续演示的数据框 —“)
print(df)
“`
read_csv()
和 read_excel()
有许多有用的参数,例如:
* sep
: 指定分隔符 (默认为逗号,sep='\t'
用于读取 TSV)
* header
: 指定哪一行作为列名 (默认为 0,即第一行)
* index_col
: 指定哪一列作为行索引
* dtype
: 指定列的数据类型
* na_values
: 指定哪些值应被视为缺失值 (NaN)
5. 查看数据
创建或加载数据后,你需要查看它以了解其结构和内容。
“`python
查看前几行 (默认为前5行)
print(“\n— df.head() —“)
print(df.head())
查看后几行 (默认为后5行)
print(“\n— df.tail(3) —“)
print(df.tail(3)) # 查看后3行
查看数据框的摘要信息 (列名、非空值数量、数据类型、内存使用等)
print(“\n— df.info() —“)
df.info()
查看数值列的描述性统计信息 (计数、均值、标准差、最小值、最大值、四分位数)
print(“\n— df.describe() —“)
print(df.describe())
查看数据框的形状 (行数, 列数)
print(“\n— df.shape —“)
print(df.shape) # 输出 (行数, 列数)
查看列名
print(“\n— df.columns —“)
print(df.columns)
查看行索引
print(“\n— df.index —“)
print(df.index)
查看数据框的所有值 (返回 NumPy 数组)
print(“\n— df.values —“)
print(df.values)
“`
这些方法能帮助你快速了解数据的大致情况。
6. 数据选择与索引
从 DataFrame 中提取特定行、列或单元格是日常操作中最频繁的任务之一。Pandas 提供了多种方法来实现这一点。
列选择
最简单的方式是使用方括号 []
和列名。
“`python
选择单列 (返回 Series)
print(“\n— 选择单列 ‘name’ —“)
print(df[‘name’])
选择多列 (返回 DataFrame)
print(“\n— 选择多列 [‘name’, ‘age’] —“)
print(df[[‘name’, ‘age’]])
注意:使用点号 ‘.’ 访问列名也可以,但不推荐用于有空格或特殊字符的列名,且容易与方法名混淆
print(df.name) # 与 df[‘name’] 效果相同,但不推荐
“`
行选择 (.loc
和 .iloc
)
选择行通常使用 .loc
或 .iloc
。这是 Pandas 中非常重要但也容易混淆的部分。
.loc
:基于标签 (Label-based) 的索引。 使用行索引标签和列名标签进行选择。.iloc
:基于整数位置 (Integer-location based) 的索引。 使用从 0 开始的整数位置进行选择,类似于 Python 列表和 NumPy 数组的索引方式。
使用 .loc
(基于标签):
“`python
print(“\n— 使用 .loc 选择行 —“)
选择单行 (通过行索引标签)
print(“选择索引为 0 的行:”)
print(df.loc[0]) # 假设默认索引是整数 0, 1, 2…
选择多行 (通过行索引标签列表)
print(“\n选择索引为 0 和 2 的行:”)
print(df.loc[[0, 2]])
选择指定行索引范围内的行 (注意:loc 的切片是包含结束标签的)
print(“\n选择索引从 1 到 3 的行 (包含 3):”)
print(df.loc[1:3])
同时选择行和列
print(“\n选择索引为 0 和 2 的行的 ‘name’ 和 ‘age’ 列:”)
print(df.loc[[0, 2], [‘name’, ‘age’]])
选择所有行的 ‘name’ 列
print(“\n选择所有行的 ‘name’ 列:”)
print(df.loc[:, ‘name’]) # :
表示所有行
选择索引从 1 到 3 的行的所有列
print(“\n选择索引从 1 到 3 的行的所有列:”)
print(df.loc[1:3, :])
“`
使用 .iloc
(基于整数位置):
“`python
print(“\n— 使用 .iloc 选择行 —“)
选择单行 (通过行位置)
print(“选择位置为 0 的行:”)
print(df.iloc[0]) # 第一行
选择多行 (通过行位置列表)
print(“\n选择位置为 0 和 2 的行:”)
print(df.iloc[[0, 2]])
选择指定行位置范围内的行 (注意:iloc 的切片是不包含结束位置的,同 Python 切片)
print(“\n选择位置从 1 到 3 的行 (不包含 3):”)
print(df.iloc[1:3]) # 第二行和第三行 (位置 1 和 2)
同时选择行和列 (使用整数位置)
print(“\n选择位置为 0 和 2 的行的位置为 1 和 2 的列 (‘name’, ‘age’):”)
print(df.iloc[[0, 2], [1, 2]]) # 位置 1 是 ‘name’,位置 2 是 ‘age’
选择所有行的位置为 1 的列
print(“\n选择所有行的位置为 1 的列 (‘name’):”)
print(df.iloc[:, 1]) # :
表示所有行,1 表示第二列
选择位置从 1 到 3 的行的所有列
print(“\n选择位置从 1 到 3 的行的所有列:”)
print(df.iloc[1:3, :])
“`
总结 .loc
vs .iloc
:
.loc
: 使用标签(行索引标签,列名)。切片包含结束标签。.iloc
: 使用整数位置(从 0 开始)。切片不包含结束位置。
对于使用默认整数索引的 DataFrame,.loc[0]
和 .iloc[0]
会选择同一行。但当你使用自定义索引时,它们的行为会不同,务必注意!
布尔索引 (条件筛选)
布尔索引是根据某一列或多列的值来选择行。这非常强大,可以用来过滤数据。
“`python
print(“\n— 布尔索引 (条件筛选) —“)
选择 age 大于 30 的所有行
print(“age 大于 30 的行:”)
print(df[df[‘age’] > 30])
选择 city 是 ‘New York’ 的所有行
print(“\ncity 是 ‘New York’ 的行:”)
print(df[df[‘city’] == ‘New York’])
组合多个条件 (使用 & 表示 ‘与’, | 表示 ‘或’, ~ 表示 ‘非’)
选择 age 大于 30 并且 city 是 ‘New York’ 的行
print(“\nage 大于 30 且 city 是 ‘New York’ 的行:”)
print(df[(df[‘age’] > 30) & (df[‘city’] == ‘New York’)])
选择 age 小于 30 或 city 是 ‘Chicago’ 的行
print(“\nage 小于 30 或 city 是 ‘Chicago’ 的行:”)
print(df[(df[‘age’] < 30) | (df[‘city’] == ‘Chicago’)])
使用 .isin() 方法选择某一列包含在列表中的值
print(“\ncity 是 ‘New York’ 或 ‘Chicago’ 的行:”)
print(df[df[‘city’].isin([‘New York’, ‘Chicago’])])
结合 .loc 进行布尔索引和列选择
print(“\n选择 age 大于 30 的行的 ‘name’ 和 ‘city’ 列:”)
print(df.loc[df[‘age’] > 30, [‘name’, ‘city’]])
“`
7. 基本数据操作
添加、删除、修改列
“`python
print(“\n— 基本数据操作:列 —“)
添加新列
df[‘is_adult’] = df[‘age’] >= 18
print(“\n添加 ‘is_adult’ 列:”)
print(df)
修改现有列的值
df[‘age’] = df[‘age’] + 1 # 所有人的年龄加 1
print(“\n年龄加 1 后:”)
print(df)
删除列
使用 del
del df[‘is_adult’]
print(“\n删除 ‘is_adult’ 列后 (使用 del):”)
print(df)
使用 .drop() 方法 (推荐,因为它更灵活,可以选择删除行或列)
axis=1 表示删除列,axis=0 表示删除行 (axis=0 是默认值)
inplace=True 会直接修改原 DataFrame,否则返回一个新 DataFrame
df_dropped_col = df.drop(‘is_adult’, axis=1) # 返回新 DataFrame
print(“\n删除 ‘is_adult’ 列后 (使用 .drop()):”)
print(df_dropped_col)
删除多列
df_multiple_dropped = df.drop([‘city’, ‘score’], axis=1)
print(“\n删除多列 ‘city’ 和 ‘score’ 后:”)
print(df_multiple_dropped)
注意:为了后续演示,我们恢复 df 到原始状态或使用副本
df = df_csv.copy()
“`
重命名列和索引
使用 .rename()
方法可以修改列名或索引标签。
“`python
print(“\n— 重命名列和索引 —“)
重命名列
df_renamed_cols = df.rename(columns={‘name’: ‘姓名’, ‘age’: ‘年龄’})
print(“\n重命名列名后:”)
print(df_renamed_cols)
重命名索引 (例如,将 id 列设置为索引并重命名索引名)
df_indexed = df.set_index(‘id’) # 将 id 列设置为索引
df_renamed_index = df_indexed.rename(index={1: ‘用户A’, 3: ‘用户C’})
print(“\n重命名索引标签后:”)
print(df_renamed_index)
注意:.rename() 默认返回新的 DataFrame,使用 inplace=True 直接修改原 DataFrame
“`
处理缺失数据 (.isnull()
, .notnull()
, .dropna()
, .fillna()
)
现实世界的数据中经常存在缺失值 (通常显示为 NaN
– Not a Number)。Pandas 提供了方便的方法来识别和处理它们。
“`python
print(“\n— 处理缺失数据 —“)
检查哪些位置是缺失值 (返回布尔型 DataFrame)
print(“\n检查缺失值:”)
print(df.isnull())
检查哪些位置不是缺失值 (返回布尔型 DataFrame)
print(“\n检查非缺失值:”)
print(df.notnull())
计算每列的缺失值数量
print(“\n每列缺失值数量:”)
print(df.isnull().sum())
删除含有缺失值的行或列
axis=0 (默认) 删除含有缺失值的行
df_dropped_rows = df.dropna(axis=0)
print(“\n删除含有缺失值的行后:”)
print(df_dropped_rows)
axis=1 删除含有缺失值的列
df_dropped_cols = df.dropna(axis=1)
print(“\n删除含有缺失值的列后:”)
print(df_dropped_cols)
.dropna() 也有其他参数,例如 how=’all’ (只删除所有值都是缺失值的行/列)
thresh=n (删除非缺失值数量少于 n 的行/列)
填充缺失值
用特定值填充
df_filled_value = df.fillna(0) # 用 0 填充所有缺失值
print(“\n用 0 填充缺失值后:”)
print(df_filled_value)
用列的均值填充 (常用方法)
mean_score = df[‘score’].mean()
df_filled_mean = df[‘score’].fillna(mean_score)
print(“\n用 score 列均值填充缺失值后的 score 列:”)
print(df_filled_mean)
使用前一个非缺失值填充 (向前填充)
df_filled_ffill = df.fillna(method=’ffill’)
print(“\n使用 ffill 填充缺失值后:”)
print(df_filled_ffill)
使用后一个非缺失值填充 (向后填充)
df_filled_bfill = df.fillna(method=’bfill’)
print(“\n使用 bfill 填充缺失值后:”)
print(df_filled_bfill)
“`
数据类型转换 (.astype()
)
有时需要改变列的数据类型,例如将字符串转换为数字,或者将浮点数转换为整数。
“`python
print(“\n— 数据类型转换 —“)
查看当前数据类型
print(“\n原始数据类型:”)
print(df.dtypes)
将 ‘age’ 列转换为 float
df[‘age’] = df[‘age’].astype(float)
print(“\n将 ‘age’ 转换为 float 后:”)
print(df.dtypes)
如果列中有缺失值 (NaN),转换为整数会失败,需要先处理缺失值
例如,先填充再转换
df[‘score’] = df[‘score’].fillna(0).astype(int) # 假设填充后可以转为整数
“`
8. 数据排序
你可以按值或按索引对 DataFrame 进行排序。
“`python
print(“\n— 数据排序 —“)
按某一列的值排序 (默认升序)
df_sorted_age = df.sort_values(by=’age’)
print(“\n按 age 升序排序:”)
print(df_sorted_age)
按某一列的值降序排序
df_sorted_age_desc = df.sort_values(by=’age’, ascending=False)
print(“\n按 age 降序排序:”)
print(df_sorted_age_desc)
按多列值排序 (先按第一列排序,再按第二列排序…)
df_sorted_multi = df.sort_values(by=[‘city’, ‘age’])
print(“\n按 city 然后按 age 排序:”)
print(df_sorted_multi)
按索引排序 (默认升序)
df_reversed_index = df.iloc[::-1] # 创建一个索引倒序的 DataFrame
df_sorted_index = df_reversed_index.sort_index()
print(“\n按索引排序:”)
print(df_sorted_index)
按索引降序排序
df_sorted_index_desc = df.sort_index(ascending=False)
print(“\n按索引降序排序:”)
print(df_sorted_index_desc)
“`
9. 数据分组与聚合 (.groupby()
)
groupby()
是 Pandas 中用于执行“分拆 (Split) – 应用 (Apply) – 组合 (Combine)”操作的核心函数。它允许你根据某一列或多列的值将数据分成组,然后对每个组独立地应用一个函数(如求和、平均值、计数等),最后将结果组合起来。
“`python
print(“\n— 数据分组与聚合 (.groupby()) —“)
按 ‘city’ 列分组,并计算每个城市的平均年龄
print(“\n按 city 分组计算平均年龄:”)
print(df.groupby(‘city’)[‘age’].mean()) # 选择 ‘age’ 列并计算平均值
按 ‘city’ 列分组,并对 ‘age’ 和 ‘score’ 两列计算平均值
print(“\n按 city 分组计算 age 和 score 的平均值:”)
print(df.groupby(‘city’)[[‘age’, ‘score’]].mean())
按 ‘city’ 分组,并计算每组的大小 (即每个城市有多少人)
print(“\n按 city 分组计算数量:”)
print(df.groupby(‘city’).size()) # 或者 .count(),但 size 更通用,包括缺失值
对分组后的对象应用多个聚合函数
print(“\n按 city 分组,计算 age 的总和、平均值和数量:”)
print(df.groupby(‘city’)[‘age’].agg([‘sum’, ‘mean’, ‘count’]))
对不同列应用不同的聚合函数
print(“\n按 city 分组,age 计算平均值,score 计算总和:”)
print(df.groupby(‘city’).agg({‘age’: ‘mean’, ‘score’: ‘sum’}))
“`
groupby()
是进行分组分析、计算汇总统计量的强大工具。
10. 数据合并 (.merge()
)
在实际应用中,数据通常分布在多个表(DataFrame)中。pd.merge()
函数允许你根据一个或多个键将不同的 DataFrame 合并起来,类似于 SQL 中的 JOIN 操作。
“`python
print(“\n— 数据合并 (.merge()) —“)
创建两个示例 DataFrame
df_info = pd.DataFrame({
‘id’: [1, 2, 3, 4, 5],
‘name’: [‘Alice’, ‘Bob’, ‘Charlie’, ‘David’, ‘Eva’]
})
df_sales = pd.DataFrame({
‘id’: [1, 2, 3, 6, 7], # 注意这里有一些 id 不在 df_info 中
‘sales’: [100, 150, 200, 50, 120]
})
print(“df_info:”)
print(df_info)
print(“\ndf_sales:”)
print(df_sales)
内连接 (inner join): 只保留两个 DataFrame 中都有的 id
df_merged_inner = pd.merge(df_info, df_sales, on=’id’, how=’inner’)
print(“\n内连接 (inner merge on ‘id’):”)
print(df_merged_inner)
左连接 (left join): 保留左边 DataFrame (df_info) 的所有 id,右边没有的用 NaN 填充
df_merged_left = pd.merge(df_info, df_sales, on=’id’, how=’left’)
print(“\n左连接 (left merge on ‘id’):”)
print(df_merged_left)
右连接 (right join): 保留右边 DataFrame (df_sales) 的所有 id,左边没有的用 NaN 填充
df_merged_right = pd.merge(df_info, df_sales, on=’id’, how=’right’)
print(“\n右连接 (right merge on ‘id’):”)
print(df_merged_right)
外连接 (outer join): 保留所有 id,没有对应值的用 NaN 填充
df_merged_outer = pd.merge(df_info, df_sales, on=’id’, how=’outer’)
print(“\n外连接 (outer merge on ‘id’):”)
print(df_merged_outer)
如果连接键在两个 DataFrame 中名字不同,可以使用 left_on 和 right_on
如果需要基于索引合并,可以使用 left_index=True, right_index=True
“`
pd.merge()
是整合来自不同来源数据的关键操作。
11. 数据输出
将处理和分析后的数据保存到文件也非常重要。
“`python
print(“\n— 数据输出 —“)
将 DataFrame 保存到 CSV 文件
index=False 表示不将 DataFrame 的索引写入文件
try:
df.to_csv(‘output_data.csv’, index=False)
print(“\nDataFrame 已保存到 output_data.csv”)
except Exception as e:
print(f”\n保存 CSV 失败:{e}”)
将 DataFrame 保存到 Excel 文件
需要安装 openpyxl 或 xlrd
try:
df.to_excel(‘output_data.xlsx’, index=False)
print(“DataFrame 已保存到 output_data.xlsx”)
except ImportError:
print(“警告:未安装 openpyxl 或 xlrd,无法保存 Excel 文件。”)
except Exception as e:
print(f”保存 Excel 失败:{e}”)
还有 to_json(), to_sql(), to_html() 等方法
“`
12. 总结与展望
恭喜你!你已经完成了 Pandas 入门的关键学习。我们从 Pandas 的基本概念、核心数据结构 Series 和 DataFrame 入手,学习了如何创建数据、查看数据概览、进行强大的数据选择和过滤、执行基本的数据清洗(处理缺失值、类型转换)、数据排序、分组聚合以及数据合并。
Pandas 的功能远不止于此。随着你对 Pandas 的深入使用,你还会接触到:
- 时间序列数据处理
- 窗口函数 (rolling, expanding)
- 数据透视表 (pivot_table)
- Categorical 数据类型
- 更高级的 Apply 操作
- 结合 Matplotlib/Seaborn 进行数据可视化
Pandas 是一个庞大而灵活的库,掌握它需要持续的练习和实践。尝试将你遇到的实际数据问题用 Pandas 来解决,多查阅官方文档,你会发现 Pandas 能极大地提高你的数据处理效率。
希望这篇详细的入门指南为你打下了坚实的基础。现在,就开始你的 Pandas 数据分析之旅吧!