Pandas Tutorial for Beginners – wiki基地


Pandas 入门教程:数据分析的得力助手

引言:为什么选择 Pandas?

在当今数据爆炸的时代,数据分析已成为一项核心技能。无论你是数据科学家、分析师、工程师,还是仅仅想更好地理解你收集的数据,高效的数据处理工具都是必不可少的。在 Python 的生态系统中,Pandas 无疑是进行数据处理和分析的王者库。

Pandas 是一个开源的 Python 库,它提供了高性能、易于使用的数据结构和数据分析工具。它的核心是 Series 和 DataFrame 这两个强大的数据结构,能够轻松处理结构化数据(表格数据),例如我们在 Excel 或数据库中常见的数据形式。

Pandas 的主要优势:

  1. 强大的数据结构: Series (一维) 和 DataFrame (二维) 能够直观地表示和操作数据。
  2. 数据读取与写入: 轻松读取多种格式的数据(CSV, Excel, SQL 数据库, HDF5 等)并写入。
  3. 数据清洗与预处理: 轻松处理缺失值、重复值,进行数据转换、格式化等。
  4. 数据选择与过滤: 基于标签或位置快速访问、选择和过滤数据。
  5. 数据聚合与分组: 强大的 groupby 功能实现复杂的数据分组和汇总。
  6. 数据合并与连接: 类似于 SQL 的 JOIN 操作,合并不同的数据集。
  7. 时间序列分析: 对时间序列数据有出色的支持。

总而言之,如果你需要使用 Python 处理和分析表格数据,Pandas 是你的首选工具。本教程将带你从零开始,逐步掌握 Pandas 的基础知识和常用操作。

前置准备

在开始之前,请确保你已经安装了 Python 和 Pandas 库。如果还没有安装 Pandas,可以使用 pip 命令:

bash
pip install pandas

通常,我们还会使用 NumPy 库,因为 Pandas 在底层依赖于 NumPy,并且很多操作会用到 NumPy 的功能。Matplotlib 和 Seaborn 库常用于数据可视化,但不是 Pandas 本身的必需品。

bash
pip install numpy matplotlib seaborn

安装完成后,我们通常会按照约定俗成的习惯导入 Pandas:

python
import pandas as pd
import numpy as np # 导入 NumPy 以备用

我们将 pandas 别名为 pd,这样写代码会更简洁方便。

Pandas 的核心数据结构

Pandas 提供了两个主要的数据结构:

  1. Series (序列): 一维带标签的数组。可以看作是带有索引的 NumPy 数组,或者单列的电子表格数据。
  2. DataFrame (数据框): 二维带标签的数据结构,由多个 Series 组成,每一列是一个 Series。可以看作是整个电子表格或数据库表。

1. Series (序列)

Series 是 Pandas 的基本数据结构之一。它类似于一维数组,但与 NumPy 数组不同的是,Series 拥有一个与之关联的索引 (Index)。这个索引可以是数字,也可以是字符串或其他可哈希的对象。

创建 Series:

最简单的创建方式是从 Python 列表或 NumPy 数组创建:

“`python

从列表创建 Series

s1 = pd.Series([1, 3, 5, np.nan, 6, 8])
print(s1)

输出:

0 1.0

1 3.0

2 5.0

3 NaN

4 6.0

5 8.0

dtype: float64

“`

上面的例子中,我们创建了一个 Series,它自动生成了一个从 0 开始的默认整数索引。np.nan 表示缺失值。

我们也可以指定索引:

“`python

指定索引创建 Series

s2 = pd.Series([10, 20, 30, 40], index=[‘a’, ‘b’, ‘c’, ‘d’])
print(s2)

输出:

a 10

b 20

c 30

d 40

dtype: int64

“`

Series 的属性和操作:

  • values: 获取 Series 的值(以 NumPy 数组形式)。
  • index: 获取 Series 的索引。
  • 可以通过索引进行访问:s2['b'] 会返回 20。
  • 支持 NumPy 的数学运算和过滤:s1 + 10, s1[s1 > 5]

“`python
print(s2.values)
print(s2.index)
print(s2[‘b’])
print(s1[s1 > 5])

输出:

[10 20 30 40]

Index([‘a’, ‘b’, ‘c’, ‘d’], dtype=’object’)

20

4 6.0

5 8.0

dtype: float64

“`

2. DataFrame (数据框)

DataFrame 是 Pandas 中最常用的数据结构,它是一个二维的表格型数据结构,可以看作是由多个 Series 组成的字典(列名作为键,Series 作为值),或者一个带有行索引和列索引的二维数组。

创建 DataFrame:

最常见的方式是从 Python 字典创建,其中字典的键是列名,值是列表或 Series:

“`python

从字典创建 DataFrame

data = {‘姓名’: [‘张三’, ‘李四’, ‘王五’, ‘赵六’],
‘年龄’: [25, 30, 22, 28],
‘城市’: [‘北京’, ‘上海’, ‘广州’, ‘深圳’]}
df = pd.DataFrame(data)
print(df)

输出:

姓名 年龄 城市

0 张三 25 北京

1 李四 30 上海

2 王五 22 广州

3 赵六 28 深圳

“`

上面创建的 DataFrame 使用了默认的整数索引。我们也可以指定行索引和列的顺序:

“`python

指定索引和列顺序创建 DataFrame

df2 = pd.DataFrame(data, index=[‘a’, ‘b’, ‘c’, ‘d’], columns=[‘姓名’, ‘城市’, ‘年龄’, ‘身高’])
print(df2)

输出:

姓名 城市 年龄 身高

a 张三 北京 25 NaN

b 李四 上海 30 NaN

c 王五 广州 22 NaN

d 赵六 深圳 28 NaN

“`

注意,由于我们指定了 ‘身高’ 列但字典中没有对应的值,Pandas 会自动用 NaN(Not a Number,表示缺失值)填充。

从列表的列表创建 DataFrame:

“`python

从列表的列表创建 DataFrame

data_list = [[‘张三’, 25, ‘北京’],
[‘李四’, 30, ‘上海’],
[‘王五’, 22, ‘广州’],
[‘赵六’, 28, ‘深圳’]]
df3 = pd.DataFrame(data_list, columns=[‘姓名’, ‘年龄’, ‘城市’])
print(df3)
“`

从文件读取数据

在实际应用中,我们最常从外部文件加载数据到 DataFrame。CSV (Comma Separated Values) 文件是最常见的数据格式之一。

“`python

假设你有一个名为 ‘students.csv’ 的文件

文件内容可能如下:

Name,Age,City

张三,25,北京

李四,30,上海

王五,22,广州

赵六,28,深圳

从 CSV 文件读取数据

try:
df_students = pd.read_csv(‘students.csv’)
print(“\n从 CSV 读取的数据:”)
print(df_students)
except FileNotFoundError:
print(“\n错误:找不到 students.csv 文件。请创建一个示例文件或跳过此步骤。”)

读取其他格式文件也很相似:

pd.read_excel(‘data.xlsx’)

pd.read_sql(‘SELECT * FROM my_table’, connection)

pd.read_json(‘data.json’)

“`

pd.read_csv() 是一个非常强大的函数,有很多参数可以控制分隔符、编码、跳过行、指定列的数据类型等等。

数据概览与检查

加载数据后,第一步通常是快速了解数据的基本情况。

“`python

假设我们已经成功加载了 df_students

if ‘df_students’ in locals():
# 查看前几行数据 (默认前5行)
print(“\ndf_students.head():”)
print(df_students.head())

# 查看后几行数据 (默认后5行)
print("\ndf_students.tail(2):")
print(df_students.tail(2)) # 可以指定行数

# 查看 DataFrame 的基本信息(列、非空值数量、数据类型、内存占用)
print("\ndf_students.info():")
df_students.info()

# 查看数值列的描述性统计信息(计数、均值、标准差、最小值、最大值、四分位数)
print("\ndf_students.describe():")
print(df_students.describe())

# 查看 DataFrame 的形状 (行数, 列数)
print("\ndf_students.shape:", df_students.shape)

# 查看列名
print("\ndf_students.columns:", df_students.columns)

# 查看行索引
print("\ndf_students.index:", df_students.index)

# 查看每列的数据类型
print("\ndf_students.dtypes:")
print(df_students.dtypes)

# 查看某个列的唯一值
print("\ndf_students['City'].unique():", df_students['City'].unique())

# 查看某个列的唯一值及其计数
print("\ndf_students['City'].value_counts():")
print(df_students['City'].value_counts())

“`

这些方法提供了数据的第一手信息,帮助你快速了解数据的结构、类型、是否有缺失值以及数值列的分布概况。

数据选择与访问

访问 DataFrame 中的数据是 Pandas 的核心操作之一。Pandas 提供了多种方式来选择列、行或特定的单元格。

1. 选择列:

可以通过列名直接选择一列或多列。选择单列返回一个 Series,选择多列返回一个 DataFrame。

“`python

选择单列 (返回 Series)

names = df_students[‘Name’]
print(“\n选择单列 ‘Name’:”)
print(names)

选择多列 (返回 DataFrame)

name_city = df_students[[‘Name’, ‘City’]]
print(“\n选择多列 [‘Name’, ‘City’]:”)
print(name_city)
“`

2. 选择行:loc 和 iloc

这是初学者容易混淆的地方,理解 lociloc 的区别至关重要。

  • .loc: 基于标签(Label)进行索引。 适用于按行索引或列名进行选择。
  • .iloc: 基于整数位置(Integer Location)进行索引。 类似于 Python 的切片,按行号和列号进行选择。

“`python

假设 df_students 的索引是默认的整数索引 (0, 1, 2, 3)

使用 .loc (基于标签,这里默认标签就是整数)

选择索引为 1 的行

row_1_loc = df_students.loc[1]
print(“\n使用 .loc 选择索引为 1 的行:”)
print(row_1_loc) # 返回 Series

选择索引从 0 到 2 的行 (包含 2)

rows_0_to_2_loc = df_students.loc[0:2]
print(“\n使用 .loc 选择索引 0 到 2 (包含):”)
print(rows_0_to_2_loc) # 返回 DataFrame

选择索引 0 和 3 的行

rows_0_and_3_loc = df_students.loc[[0, 3]]
print(“\n使用 .loc 选择索引 0 和 3:”)
print(rows_0_and_3_loc) # 返回 DataFrame

使用 .iloc (基于整数位置)

选择位置为 1 的行 (即第二行)

row_1_iloc = df_students.iloc[1]
print(“\n使用 .iloc 选择位置为 1 的行 (第二行):”)
print(row_1_iloc) # 返回 Series

选择位置从 0 到 2 的行 (不包含 2)

rows_0_to_2_iloc = df_students.iloc[0:2]
print(“\n使用 .iloc 选择位置 0 到 2 (不包含 2):”)
print(rows_0_to_2_iloc) # 返回 DataFrame

选择位置 0 和 3 的行

rows_0_and_3_iloc = df_students.iloc[[0, 3]]
print(“\n使用 .iloc 选择位置 0 和 3:”)
print(rows_0_and_3_iloc) # 返回 DataFrame
“`

同时选择行和列:

lociloc 都可以接受逗号分隔的两个参数,第一个参数指定行,第二个参数指定列。

“`python

使用 .loc 选择索引 1 到 3 的行,以及 ‘Name’ 和 ‘Age’ 列

subset_loc = df_students.loc[1:3, [‘Name’, ‘Age’]]
print(“\n使用 .loc 选择行 1-3 和指定列:”)
print(subset_loc)

使用 .iloc 选择位置 1 到 3 的行 (不包含 3),以及位置 0 到 2 的列 (不包含 2)

subset_iloc = df_students.iloc[1:3, 0:2]
print(“\n使用 .iloc 选择位置 1-3 (不含) 和列位置 0-2 (不含):”)
print(subset_iloc)

选择特定的单元格

cell_loc = df_students.loc[0, ‘City’] # 第一行 ‘City’ 列的值
print(“\n使用 .loc 选择特定单元格 (第一行 ‘City’):”, cell_loc)

cell_iloc = df_students.iloc[0, 2] # 位置 0 行,位置 2 列的值
print(“使用 .iloc 选择特定单元格 (位置 0 行,位置 2 列):”, cell_iloc)
“`

数据过滤 (条件筛选)

根据某个或多个条件过滤数据是 Pandas 的常用功能。这通过布尔索引实现。

“`python

筛选年龄大于 25 的学生

younger_than_25 = df_students[df_students[‘Age’] > 25]
print(“\n年龄大于 25 的学生:”)
print(younger_than_25)

筛选城市是 ‘北京’ 的学生

from_beijing = df_students[df_students[‘City’] == ‘北京’]
print(“\n城市是 ‘北京’ 的学生:”)
print(from_beijing)

组合多个条件 (使用 & 表示与,| 表示或,~ 表示非)

筛选年龄大于 25 并且城市是 ‘上海’ 或 ‘深圳’ 的学生

complex_filter = df_students[(df_students[‘Age’] > 25) & ((df_students[‘City’] == ‘上海’) | (df_students[‘City’] == ‘深圳’))]
print(“\n年龄大于 25 且城市为上海或深圳的学生:”)
print(complex_filter)

使用 isin() 方法进行多值筛选

cities_to_filter = [‘上海’, ‘深圳’]
complex_filter_isin = df_students[(df_students[‘Age’] > 25) & (df_students[‘City’].isin(cities_to_filter))]
print(“\n使用 isin() 进行多值筛选:”)
print(complex_filter_isin)
“`

处理缺失数据

实际数据中经常包含缺失值(通常表示为 NaN)。Pandas 提供了便捷的方法来识别、删除或填充缺失值。

“`python

创建一个包含缺失值的示例 DataFrame

data_missing = {‘A’: [1, 2, np.nan, 4],
‘B’: [5, np.nan, np.nan, 8],
‘C’: [9, 10, 11, 12]}
df_missing = pd.DataFrame(data_missing)
print(“\n包含缺失值的 DataFrame:”)
print(df_missing)

检查哪些位置是缺失值

print(“\ndf_missing.isnull():”)
print(df_missing.isnull()) # 返回布尔型 DataFrame

检查哪些位置不是缺失值

print(“\ndf_missing.notnull():”)
print(df_missing.notnull())

统计每列的缺失值数量

print(“\ndf_missing.isnull().sum():”)
print(df_missing.isnull().sum()) # 对于 DataFrame,sum(轴=0) 默认按列求和

删除包含缺失值的行

df_dropped_rows = df_missing.dropna()
print(“\n删除包含缺失值的行:”)
print(df_dropped_rows)

删除包含缺失值的列 (how=’all’ 表示只删除全为缺失值的列)

df_dropped_cols = df_missing.dropna(axis=1, how=’any’) # axis=1 表示列,how=’any’ 表示只要有缺失值就删除该列
print(“\n删除包含缺失值的列:”)
print(df_dropped_cols)

填充缺失值

用一个固定值填充

df_filled_0 = df_missing.fillna(0)
print(“\n用 0 填充缺失值:”)
print(df_filled_0)

用该列的均值填充

mean_A = df_missing[‘A’].mean()
df_filled_mean = df_missing.fillna({‘A’: mean_A, ‘B’: df_missing[‘B’].median()}) # 可以为不同列指定不同的填充值
print(“\n用列均值/中位数填充缺失值:”)
print(df_filled_mean)

使用前向填充 (用前一个非缺失值填充)

df_filled_ffill = df_missing.fillna(method=’ffill’)
print(“\n前向填充缺失值 (ffill):”)
print(df_filled_ffill)

使用后向填充 (用后一个非缺失值填充)

df_filled_bfill = df_missing.fillna(method=’bfill’)
print(“\n后向填充缺失值 (bfill):”)
print(df_filled_bfill)
``
请注意,
dropna()fillna()默认情况下不会修改原始 DataFrame,而是返回一个新的 DataFrame。如果想修改原始 DataFrame,可以使用inplace=True参数,例如df_missing.dropna(inplace=True)`。

数据处理与转换

Pandas 提供了丰富的数据处理和转换功能。

1. 添加/修改/删除列:

添加新列就像给字典添加新的键值对一样简单:

“`python

添加新列 ‘Score’

df_students[‘Score’] = [95, 88, 75, 92]
print(“\n添加 ‘Score’ 列:”)
print(df_students)

添加基于现有列计算的新列 ‘Age_in_5_Years’

df_students[‘Age_in_5_Years’] = df_students[‘Age’] + 5
print(“\n添加计算得出的 ‘Age_in_5_Years’ 列:”)
print(df_students)

修改现有列的值 (例如,将所有城市名称加上后缀)

df_students[‘City’] = df_students[‘City’] + ‘市’
print(“\n修改 ‘City’ 列:”)
print(df_students)

删除列

df_students_dropped = df_students.drop(‘Age_in_5_Years’, axis=1) # axis=1 表示删除列
print(“\n删除 ‘Age_in_5_Years’ 列:”)
print(df_students_dropped)

删除多列

df_students_dropped_multi = df_students.drop([‘Score’, ‘City’], axis=1)
print(“\n删除多列 ‘Score’ 和 ‘City’:”)
print(df_students_dropped_multi)
“`

2. 应用函数 (apply):

apply() 方法可以沿 DataFrame 的轴(行或列)应用函数。

“`python

对 ‘Age’ 列的每个值应用一个函数 (例如,判断是否成年)

df_students[‘Is_Adult’] = df_students[‘Age’].apply(lambda x: ‘Yes’ if x >= 18 else ‘No’)
print(“\n使用 apply() 添加 ‘Is_Adult’ 列:”)
print(df_students)

对 DataFrame 的每一行应用函数 (axis=1)

例如,创建一个 ‘Name_Age’ 列,格式为 “姓名 (年龄)”

df_students[‘Name_Age’] = df_students.apply(lambda row: f”{row[‘Name’]} ({row[‘Age’]})”, axis=1)
print(“\n使用 apply(axis=1) 创建 ‘Name_Age’ 列:”)
print(df_students)
“`

分组和聚合

groupby() 是 Pandas 中进行数据分组和聚合分析的强大工具,类似于 SQL 中的 GROUP BY。它将 DataFrame 按照指定的列(或多个列)分割成若干个组,然后对每个组独立地应用一个函数(聚合、转换或过滤)。

“`python

创建一个示例 DataFrame 用于分组

data_sales = {‘Category’: [‘A’, ‘B’, ‘A’, ‘C’, ‘B’, ‘A’, ‘C’],
‘Product’: [‘X’, ‘Y’, ‘Z’, ‘W’, ‘V’, ‘U’, ‘T’],
‘Sales’: [100, 150, 120, 80, 200, 110, 90],
‘Quantity’: [10, 15, 12, 8, 20, 11, 9]}
df_sales = pd.DataFrame(data_sales)
print(“\n用于分组的销售数据:”)
print(df_sales)

按 ‘Category’ 列分组,并计算每组的总销售额

sales_by_category = df_sales.groupby(‘Category’)[‘Sales’].sum()
print(“\n按 ‘Category’ 分组计算总销售额:”)
print(sales_by_category)

按 ‘Category’ 分组,并计算每组的平均销售额和总数量

sales_stats_by_category = df_sales.groupby(‘Category’).agg({‘Sales’: ‘mean’, ‘Quantity’: ‘sum’})
print(“\n按 ‘Category’ 分组计算平均销售额和总数量:”)
print(sales_stats_by_category)

按多个列分组 (例如 Category 和 Product)

sales_by_category_product = df_sales.groupby([‘Category’, ‘Product’])[‘Sales’].sum()

print(“\n按 ‘Category’ 和 ‘Product’ 分组计算总销售额:”)

print(sales_by_category_product)

print(type(sales_by_category_product)) # 多层索引的 Series

“`

groupby() 返回一个 GroupBy 对象,你需要对这个对象应用一个聚合函数(如 sum(), mean(), count(), size(), min(), max(), std(), var(), first(), last(), agg() 等)才能得到结果。

数据保存

分析完成后,你可能需要将结果保存到文件。同样,最常见的格式是 CSV。

“`python

将 DataFrame 保存为 CSV 文件

index=False 表示不将 DataFrame 的行索引写入文件

df_students.to_csv(‘students_processed.csv’, index=False)
print(“\nDataFrame 已保存到 students_processed.csv (不包含索引)”)

如果你想包含索引

df_students.to_csv(‘students_processed_with_index.csv’, index=True)

保存为 Excel 文件 (需要安装 openpyxl 或 xlsxwriter 库)

pip install openpyxl

df_students.to_excel(‘students_processed.xlsx’, index=False)

“`

总结与下一步

恭喜你!你已经学习了 Pandas 的基础知识,包括:

  • Pandas 的引入和核心数据结构 (Series 和 DataFrame)
  • 创建和加载数据 (从字典、列表、CSV 文件)
  • 查看数据概览 (head, info, describe, shape, columns, index, dtypes)
  • 数据选择和访问 ([], .loc, .iloc)
  • 数据过滤 (布尔索引)
  • 处理缺失值 (isnull, dropna, fillna)
  • 基本数据处理 (apply, 添加/修改/删除列)
  • 数据分组和聚合 (groupby, agg)
  • 数据保存 (to_csv)

这只是 Pandas 功能的冰山一角。Pandas 还有更多强大的功能,例如:

  • 数据合并 (merge, join, concat)
  • 透视表 (pivot_table)
  • 时间序列处理
  • 类别数据处理
  • 更高级的数据清洗和转换技术

掌握了本教程的基础知识,你已经具备了使用 Pandas 进行初步数据分析和处理的能力。接下来的学习可以深入研究 Pandas 的官方文档,通过实际的项目练习来巩固和扩展你的技能。结合 Matplotlib 和 Seaborn 进行数据可视化,能让你的数据分析结果更加直观和有说服力。

不断实践,探索更多 Pandas 的功能,它将成为你在数据世界里最强大的工具之一!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部