我无法直接将文章写入文件,因为我没有 write_file 工具。但我可以把文章内容直接输出给你。
Python Pandas 详解:从入门到实践
Python Pandas 是一个强大的数据处理和分析库,为 Python 编程语言带来了高性能、易于使用的数据结构和数据分析工具。它已成为数据科学家、数据分析师以及任何需要处理结构化数据的 Python 开发者不可或缺的工具。
1. 什么是 Pandas?
Pandas 的核心是其两种主要的数据结构:Series 和 DataFrame。它建立在 NumPy 库之上,提供了快速、灵活且富有表现力的数据结构,旨在使“关系型”或“标签化”数据的使用变得简单直观。它特别适用于处理表格数据(如 SQL 表或 Excel 表格)、有序和无序(非固定频率)时间序列数据、以及带有行和列标签的任意矩阵数据。
2. 为什么使用 Pandas?
- 数据清洗与准备: Pandas 提供了丰富的函数来处理缺失数据、重复数据、格式不一致的数据等,极大地简化了数据清洗的过程。
- 数据探索与分析: 轻松地进行数据筛选、排序、分组、聚合等操作,帮助用户快速洞察数据。
- 数据加载与存储: 支持多种文件格式(如 CSV、Excel、SQL 数据库、JSON、HDF5 等)的数据读取和写入。
- 高效性能: 底层使用 C 语言编写的优化代码,使得 Pandas 在处理大量数据时依然保持高效。
3. 安装与导入
要使用 Pandas,首先需要安装它。推荐使用 pip 或 conda 进行安装:
bash
pip install pandas numpy
安装完成后,可以在 Python 代码中导入 Pandas:
python
import pandas as pd
import numpy as np
通常使用 pd 作为 Pandas 的别名,这是社区的约定俗成。
4. 核心数据结构
4.1 Series(序列)
Series 是一种一维带标签的数组,可以存储任何数据类型(整数、浮点数、字符串、Python 对象等)。它由两部分组成:数据(values)和索引(index)。
创建 Series:
“`python
从列表创建
s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(“从列表创建 Series:\n”, s)
从 NumPy 数组创建,指定索引
dates = pd.date_range(“20230101”, periods=6)
s2 = pd.Series([10, 20, 30, 40, 50, 60], index=dates)
print(“\n从数组创建 Series (带索引):\n”, s2)
从字典创建
data_dict = {‘a’: 10, ‘b’: 20, ‘c’: 30}
s3 = pd.Series(data_dict)
print(“\n从字典创建 Series:\n”, s3)
“`
Series 的基本操作:
python
print("\nSeries 的值:\n", s.values)
print("\nSeries 的索引:\n", s.index)
print("\n获取第一个元素:", s[0])
print("\n按标签获取元素:", s3['b'])
print("\nSeries 运算:\n", s * 2)
4.2 DataFrame(数据帧)
DataFrame 是 Pandas 中最常用的数据结构,它是一个二维的、大小可变、可能异构的表格数据结构,类似于电子表格或 SQL 表。它有行和列,每列可以是不同的数据类型。
创建 DataFrame:
“`python
从字典创建 DataFrame
data = {
‘Name’: [‘Alice’, ‘Bob’, ‘Charlie’, ‘David’],
‘Age’: [25, 30, 35, 28],
‘City’: [‘New York’, ‘Paris’, ‘London’, ‘Berlin’]
}
df = pd.DataFrame(data)
print(“从字典创建 DataFrame:\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(“\n从 NumPy 数组创建 DataFrame (带索引和列名):\n”, df2)
“`
DataFrame 的基本属性:
python
print("\nDataFrame 的形状 (行数, 列数):", df.shape)
print("\nDataFrame 的列名:", df.columns)
print("\nDataFrame 的索引:", df.index)
print("\nDataFrame 每列的数据类型:\n", df.dtypes)
print("\n查看 DataFrame 的前几行 (默认为5行):\n", df.head(2))
print("\n查看 DataFrame 的后几行 (默认为5行):\n", df.tail(1))
print("\nDataFrame 的统计描述:\n", df.describe())
访问 DataFrame 中的数据:
- 选择列:
python
print("\n选择单列 'Name':\n", df['Name'])
print("\n选择多列 ['Name', 'Age']:\n", df[['Name', 'Age']]) -
选择行(使用
loc和iloc):loc:基于标签(label)的索引。iloc:基于整数位置(integer position)的索引。
“`python
使用 loc (通过行标签和列标签)
print(“\n使用 loc 选择第一行:\n”, df.loc[0])
print(“\n使用 loc 选择多行:\n”, df.loc[0:2, [‘Name’, ‘City’]]) # 0到2行(包含2),Name和City列使用 iloc (通过整数位置)
print(“\n使用 iloc 选择第一行:\n”, df.iloc[0])
print(“\n使用 iloc 选择多行:\n”, df.iloc[0:3, [0, 2]]) # 0到2行(不包含3),第0和第2列
“`
5. 数据加载与保存
Pandas 提供了方便的函数来读取和写入各种数据格式。
“`python
创建一个示例 DataFrame 用于保存
data_to_save = {
‘Product’: [‘Apple’, ‘Banana’, ‘Orange’],
‘Price’: [1.5, 0.75, 1.2],
‘Quantity’: [100, 200, 150]
}
df_save = pd.DataFrame(data_to_save)
保存到 CSV 文件
df_save.to_csv(‘products.csv’, index=False) # index=False 表示不保存行索引
print(“\n数据已保存到 products.csv (示例,实际未写入文件)”)
从 CSV 文件读取
df_loaded = pd.read_csv(‘products.csv’)
print(“\n从 products.csv 读取数据:\n”, df_loaded)
保存到 Excel 文件 (需要安装 openpyxl 或 xlwt/xlrd)
pip install openpyxl
df_save.to_excel(‘products.xlsx’, index=False)
print(“\n数据已保存到 products.xlsx (示例,实际未写入文件)”)
从 Excel 文件读取
df_excel_loaded = pd.read_excel(‘products.xlsx’)
print(“\n从 products.xlsx 读取数据:\n”, df_excel_loaded)
“`
6. 数据清洗与预处理
6.1 处理缺失数据
缺失数据通常表示为 NaN (Not a Number)。
“`python
df_missing = pd.DataFrame({
‘A’: [1, 2, np.nan, 4],
‘B’: [5, np.nan, np.nan, 8],
‘C’: [9, 10, 11, 12]
})
print(“\n原始 DataFrame (含缺失值):\n”, df_missing)
检测缺失值
print(“\n检测缺失值:\n”, df_missing.isnull())
print(“\n每列的缺失值数量:\n”, df_missing.isnull().sum())
删除含有缺失值的行
df_dropped_rows = df_missing.dropna()
print(“\n删除含有缺失值的行:\n”, df_dropped_rows)
删除所有列均为缺失值的行
df_dropped_all_nan = df_missing.dropna(how=’all’)
填充缺失值
df_filled_zero = df_missing.fillna(0)
print(“\n缺失值填充为 0:\n”, df_filled_zero)
使用前一个有效值填充 (forward fill)
df_filled_ffill = df_missing.fillna(method=’ffill’)
print(“\n缺失值使用 ffill 填充:\n”, df_filled_ffill)
使用列的平均值填充
df_filled_mean = df_missing.fillna(df_missing.mean())
print(“\n缺失值使用列平均值填充:\n”, df_filled_mean)
“`
6.2 更改数据类型
“`python
df_types = pd.DataFrame({‘col1’: [‘1’, ‘2’, ‘3’], ‘col2’: [‘A’, ‘B’, ‘C’]})
print(“\n原始 DataFrame 数据类型:\n”, df_types.dtypes)
将 ‘col1’ 从字符串更改为整数
df_types[‘col1’] = df_types[‘col1’].astype(int)
print(“\n更改数据类型后的 DataFrame:\n”, df_types.dtypes)
“`
6.3 删除重复项
“`python
df_duplicates = pd.DataFrame({
‘col1’: [1, 2, 1, 3],
‘col2’: [‘A’, ‘B’, ‘A’, ‘C’]
})
print(“\n原始 DataFrame (含重复项):\n”, df_duplicates)
删除所有列都重复的行
df_no_duplicates = df_duplicates.drop_duplicates()
print(“\n删除重复行后的 DataFrame:\n”, df_no_duplicates)
基于特定列删除重复项 (保留第一次出现)
df_no_duplicates_col1 = df_duplicates.drop_duplicates(subset=[‘col1’])
print(“\n基于 ‘col1’ 删除重复项:\n”, df_no_duplicates_col1)
“`
6.4 重命名列
“`python
df_rename = pd.DataFrame({‘old_name_A’: [1, 2], ‘old_name_B’: [3, 4]})
print(“\n原始 DataFrame (待重命名):\n”, df_rename)
df_renamed = df_rename.rename(columns={‘old_name_A’: ‘new_name_X’, ‘old_name_B’: ‘new_name_Y’})
print(“\n重命名列后的 DataFrame:\n”, df_renamed)
“`
7. 数据选择和过滤
7.1 条件筛选
“`python
df_filter = pd.DataFrame({
‘Category’: [‘A’, ‘B’, ‘A’, ‘C’, ‘B’],
‘Value’: [10, 20, 15, 25, 30]
})
print(“\n原始 DataFrame (用于筛选):\n”, df_filter)
选择 Category 为 ‘A’ 的行
filtered_df_A = df_filter[df_filter[‘Category’] == ‘A’]
print(“\nCategory 为 ‘A’ 的行:\n”, filtered_df_A)
组合条件
filtered_df_multi = df_filter[(df_filter[‘Category’] == ‘B’) & (df_filter[‘Value’] > 20)]
print(“\nCategory 为 ‘B’ 且 Value > 20 的行:\n”, filtered_df_multi)
“`
7.2 使用 query()
query() 方法提供了一种更简洁、更类似 SQL 的方式进行条件筛选。
python
queried_df = df_filter.query("Category == 'A' and Value > 12")
print("\n使用 query() 筛选:\n", queried_df)
7.3 使用 isin()
isin() 用于筛选列值是否在给定列表中。
python
filtered_isin = df_filter[df_filter['Category'].isin(['A', 'C'])]
print("\nCategory 在 ['A', 'C'] 中的行:\n", filtered_isin)
8. 数据分组与聚合
groupby() 是 Pandas 中最强大的功能之一,它允许你根据一个或多个列的值将数据拆分成组,然后对每个组独立地执行一些操作(聚合、转换、过滤)。
“`python
df_group = pd.DataFrame({
‘Region’: [‘East’, ‘West’, ‘East’, ‘West’, ‘East’],
‘Salesperson’: [‘Alice’, ‘Bob’, ‘Alice’, ‘Charlie’, ‘David’],
‘Sales’: [100, 150, 120, 200, 180]
})
print(“\n原始 DataFrame (用于分组):\n”, df_group)
按 ‘Region’ 分组并计算每个区域的总销售额
grouped_sales = df_group.groupby(‘Region’)[‘Sales’].sum()
print(“\n按 Region 分组的总销售额:\n”, grouped_sales)
按 ‘Region’ 分组并计算每个区域的平均销售额和销售数量
grouped_stats = df_group.groupby(‘Region’)[‘Sales’].agg([‘mean’, ‘count’])
print(“\n按 Region 分组的平均销售额和数量:\n”, grouped_stats)
按多个列分组
grouped_multi = df_group.groupby([‘Region’, ‘Salesperson’])[‘Sales’].sum()
print(“\n按 Region 和 Salesperson 分组的总销售额:\n”, grouped_multi)
“`
9. 合并、连接和连接 DataFrame
9.1 concat()(连接)
concat() 函数用于沿轴(默认是行)连接 Pandas 对象。
“`python
df1 = pd.DataFrame({‘A’: [‘A0’, ‘A1’], ‘B’: [‘B0’, ‘B1’]})
df2 = pd.DataFrame({‘A’: [‘A2’, ‘A3’], ‘B’: [‘B2’, ‘B3’]})
print(“\nDataFrame 1:\n”, df1)
print(“\nDataFrame 2:\n”, df2)
沿行方向连接 (默认)
result_rows = pd.concat([df1, df2])
print(“\n沿行方向连接:\n”, result_rows)
沿列方向连接
result_cols = pd.concat([df1, df2], axis=1)
print(“\n沿列方向连接:\n”, result_cols)
“`
9.2 merge()(合并)
merge() 函数用于通过一个或多个键将 DataFrame 中的行组合起来,类似于 SQL 中的 JOIN 操作。
“`python
df_left = pd.DataFrame({‘key’: [‘K0’, ‘K1’, ‘K2’, ‘K3’],
‘A’: [‘A0’, ‘A1’, ‘A2’, ‘A3’],
‘B’: [‘B0’, ‘B1’, ‘B2’, ‘B3’]})
df_right = pd.DataFrame({‘key’: [‘K0’, ‘K1’, ‘K4’, ‘K5’],
‘C’: [‘C0’, ‘C1’, ‘C2’, ‘C3’],
‘D’: [‘D0’, ‘D1’, ‘D2’, ‘D3’]})
print(“\nDataFrame Left:\n”, df_left)
print(“\nDataFrame Right:\n”, df_right)
内连接 (inner merge): 只保留两个 DataFrame 中 ‘key’ 列都存在的行
merged_inner = pd.merge(df_left, df_right, on=’key’, how=’inner’)
print(“\n内连接:\n”, merged_inner)
外连接 (outer merge): 保留所有行,缺失值用 NaN 填充
merged_outer = pd.merge(df_left, df_right, on=’key’, how=’outer’)
print(“\n外连接:\n”, merged_outer)
左连接 (left merge): 保留左边 DataFrame 的所有行
merged_left = pd.merge(df_left, df_right, on=’key’, how=’left’)
print(“\n左连接:\n”, merged_left)
“`
9.3 join()(连接)
join() 是一个方便的方法,用于连接具有相同或相似索引的 DataFrame,或者通过一个列作为键进行连接。它默认是左连接,并且通常在索引上进行操作。
“`python
df_join_left = pd.DataFrame({‘A’: [‘A0’, ‘A1’], ‘B’: [‘B0’, ‘B1’]}, index=[‘K0’, ‘K1’])
df_join_right = pd.DataFrame({‘C’: [‘C0’, ‘C1’], ‘D’: [‘D0’, ‘D1’]}, index=[‘K0’, ‘K2’])
print(“\nDataFrame Join Left:\n”, df_join_left)
print(“\nDataFrame Join Right:\n”, df_join_right)
默认左连接 (基于索引)
joined_df = df_join_left.join(df_join_right)
print(“\n默认左连接:\n”, joined_df)
内连接
joined_inner_df = df_join_left.join(df_join_right, how=’inner’)
print(“\n内连接:\n”, joined_inner_df)
“`
10. 时间序列分析(简介)
Pandas 在时间序列数据处理方面表现卓越。
“`python
创建日期范围作为索引
dates_ts = pd.date_range(‘2023-01-01′, periods=5, freq=’D’)
ts = pd.Series(np.random.randn(5), index=dates_ts)
print(“\n时间序列数据:\n”, ts)
将字符串转换为 datetime 对象
df_time = pd.DataFrame({‘date’: [‘2023-01-01’, ‘2023-01-02’, ‘2023-01-03’],
‘value’: [10, 20, 30]})
df_time[‘date’] = pd.to_datetime(df_time[‘date’])
print(“\n转换为 datetime 类型后的 DataFrame:\n”, df_time)
print(“日期列类型:”, df_time[‘date’].dtype)
设置日期列为索引
df_time = df_time.set_index(‘date’)
print(“\n日期列设置为索引:\n”, df_time)
重采样 (例如,按周求和)
resampled_weekly = ts.resample(‘W’).sum()
print(“\n按周重采样求和:\n”, resampled_weekly)
“`
11. 总结
Python Pandas 是一个功能强大且灵活的数据分析库。通过 Series 和 DataFrame 这两种核心数据结构,它提供了从数据加载、清洗、预处理到数据分析、聚合、合并的完整工具集。无论是处理简单的表格数据还是复杂的时间序列数据,Pandas 都能显著提高数据处理的效率和代码的可读性。
希望这篇文章能帮助您从入门到实践,熟练掌握 Pandas 的基本功能。随着您对数据分析需求的深入,将会有更多高级功能等待您去探索,例如多级索引、窗口函数、类别数据处理等。持续练习和项目实践是掌握 Pandas 的最佳途径。
进一步学习资源:
- Pandas 官方文档:https://pandas.pydata.org/docs/
- Wes McKinney 的《Python for Data Analysis》一书。
- 在线教程和数据科学平台(如 Kaggle、DataCamp 等)。