Python数据分析三剑客:Matplotlib、NumPy和Pandas

Python 数据分析中最重要的三个库:Matplotlib、NumPy 和 Pandas,这三个库是 Python 数据分析领域的基石,它们通常配合使用,构成了一个强大而高效的数据处理、分析和可视化工具集。

1. NumPy (Numerical Python)

是什么?

NumPy 是 Python 中用于科学计算的核心库。它提供了一个高性能的多维数组对象( ndarray )以及用于处理这些数组的工具。可以理解为 Python 中进行数值计算的基础,尤其擅长处理大型数组和矩阵。

核心数据结构

  • ndarray (N-dimensional array):这是 NumPy 最重要的对象。它是一个同质的(所有元素类型相同)多维数组,其元素在 内存中是连续存储 的。这使得 NumPy 在处理大量数值数据时比 Python 内置的列表(list)更高效。

主要特点和功能

  1. 高效的多维数组对象: ndarray 的速度和内存效率远高于 Python 的列表,尤其是在处理大型数据集时。

  2. 广播 (Broadcasting): NumPy 允许对形状不同的数组进行算术运算,而无需显式地改变数组形状。它会自动调整较小数组的形状以匹配较大数组,然后执行元素级运算。

  3. 向量化运算: NumPy支持对整个数组进行元素级运算,而无需编写显式的循环。例如,两个 NumPy 数组相加,会自动将对应位置的元素相加。这种向量化操作通常比 Python 循环快得多。

  4. 数学函数库: 提供了大量的数学函数(通用函数 ufunc),可以对数组中的每个元素进行操作,如 sin, cos, exp, sqrt 等。

  5. 线性代数、傅里叶变换、随机数生成等功能: 内置了丰富的数学和统计函数模块,方便进行复杂的数值计算。

  6. 与其他库的集成: NumPy 是许多其他科学计算库(包括 Pandas、Matplotlib、SciPy、scikit-learn 等)的基础。

为什么重要?

  • 性能: 底层实现由 C 或 Fortran 编写,计算速度非常快,是 Python 进行大规模数值计算的首选。

  • 基础: 它提供了高效的数据结构和计算能力,是构建更高级数据分析库(如 Pandas)的基础。

  • 简洁: 通过向量化操作,可以用更少的代码完成复杂的数值计算任务。

简单示例

import numpy as np

# 创建一个NumPy数组
arr1 = np.array([1, 2, 3, 4, 5])
print("NumPy 数组 arr1:", arr1)
print("数组类型:", type(arr1))
print("数组维度:", arr1.shape) # (5,) 表示1维,5个元素

# 创建一个二维数组 (矩阵)
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print("\nNumPy 数组 arr2 (二维):\n", arr2)
print("数组维度:", arr2.shape) # (2, 3) 表示2行3列

# 向量化运算:数组与标量相乘
arr_mult = arr1 * 2
print("\narr1 * 2:", arr_mult) # 每个元素都乘以2

# 向量化运算:两个数组相加 (要求形状相同)
arr3 = np.array([5, 4, 3, 2, 1])
arr_sum = arr1 + arr3
print("arr1 + arr3:", arr_sum) # 对应元素相加

# 广播示例:二维数组与一维数组相加
arr4 = np.array([10, 20, 30])
arr_broadcast = arr2 + arr4 # [10, 20, 30] 会被广播成 [[10, 20, 30], [10, 20, 30]]
print("\narr2 + arr4 (广播):\n", arr_broadcast)

# 使用通用函数
arr_sqrt = np.sqrt(arr1)
print("arr1 的平方根:", arr_sqrt)

# 线性代数:矩阵乘法 (使用 @ 运算符 或 np.dot())
mat1 = np.array([[1, 2], [3, 4]])
mat2 = np.array([[5, 6], [7, 8]])
mat_prod = mat1 @ mat2 # 或 np.dot(mat1, mat2)
print("\n矩阵乘法:\n", mat_prod)

2. Pandas (Panel Data)

是什么

Pandas 是一个强大的开源库,用于进行数据操作、分析和清洗。它构建在 NumPy 之上,提供了更高级、更易于使用的 带标签的数据结构,特别适合处理表格数据(类似电子表格或数据库表)。

核心数据结构

  1. Series :一维带标签的数组。可以看作是一个带有索引(index)的 NumPy 数组,或者一个定长的有序字典。它由数据(values)和与之关联的索引(index)组成。

  2. DataFrame:二维带标签的数据结构,是 Pandas 中最常用的对象。可以看作是由多个 Series 组成,共享同一个索引(行索引),同时每列有自己的标签(列名)。它非常类似于电子表格或 SQL 表。

主要特点和功能

  1. 灵活的数据读取和写入: 支持读取多种格式的数据文件,如 CSV ( pd.read_csv )、Excel ( pd.read_excel )、SQL 数据库 ( pd.read_sql )、JSON、HDF5 等,并能方便地将数据写入这些格式。

  2. 便捷的数据清洗和准备: 轻松处理缺失数据 ( isnull(), dropna(), fillna() )、重复数据 ( drop_duplicates() )、数据转换、数据重塑( pivot, melt )等。

  3. 强大的数据选择、过滤和切片: 基于标签 ( .loc[] ) 或整数位置 ( .iloc[] ) 进行灵活的数据子集选取。

  4. 数据对齐: 在进行数据操作时,Pandas 会根据索引自动对齐数据,避免因为顺序不同导致错误。

  5. 分组聚合 (GroupBy): 提供非常灵活的分组( groupby() )和聚合( agg(), sum(), mean(), count() 等)功能,用于按某个或多个键对数据进行分组,然后对每个组执行计算。

  6. 数据合并和连接: 支持类似数据库的合并( merge() )和连接( concat() )操作,用于组合来自不同来源的数据。

  7. 时间序列功能: 对时间序列数据有专门的支持,包括日期范围生成、频率转换、移动窗口统计等。

  8. 内置可视化: Pandas 的对象(Series 和 DataFrame)拥有基于 Matplotlib 的绘图方法,可以直接快速绘制数据。

为什么重要?

  • 易用性: 提供了直观易懂的数据结构和丰富的操作方法,使得数据清洗、转换和分析变得非常便捷。

  • 功能全面: 涵盖了数据处理、分析的绝大部分常见任务。

  • 与实际数据结构匹配: DataFrame 完美契合了现实世界中常见的表格数据形式。

简单示例


import pandas as pd
import numpy as np # Pandas 内部使用 NumPy

# 创建一个Series
s = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
print("Pandas Series:\n", s)
print("Series 值:", s.values)
print("Series 索引:", s.index)

# 创建一个DataFrame
data = {
    '城市': ['北京', '上海', '广州', '深圳', '成都'],
    '人口': [2154, 2487, 1530, 1756, 1633], # 假设单位万人
    '面积': [16411, 6340, 7434, 1997, 14335], # 假设单位平方公里
    '是否省会': [True, False, False, False, True]
}
df = pd.DataFrame(data)
print("\nPandas DataFrame:\n", df)

# 查看 DataFrame 的基本信息
print("\nDataFrame 信息:")
df.info()

# 查看 DataFrame 的前几行
print("\nDataFrame 前2行:")
print(df.head(2))

# 选择单列 (返回一个Series)
population = df['人口']
print("\n'人口' 列:\n", population)

# 选择多列 (返回一个DataFrame)
subset = df[['城市', '人口']]
print("\n'城市' 和 '人口' 列:\n", subset)

# 使用 .loc[] 按标签选择行和列
row_guangzhou = df.loc[2] # 按索引标签2选择行
print("\n索引为2的行 (广州):\n", row_guangzhou)
subset_beijing_shanghai = df.loc[0:1, ['城市', '人口']] # 选择索引为0和1行的'城市'和'人口'列
print("\n索引0和1行的'城市'和'人口'列:\n", subset_beijing_shanghai)

# 使用 .iloc[] 按位置选择行和列
first_row = df.iloc[0] # 选择第0行 (第一行)
print("\n第一行:\n", first_row)
subset_by_pos = df.iloc[[0, 4], [0, 1]] # 选择第0行和第4行,以及第0列和第1列
print("\n位置0和4行的位置0和1列:\n", subset_by_pos)

# 条件过滤
large_cities = df[df['人口'] > 1700] # 选择人口大于1700万的城市
print("\n人口大于1700万的城市:\n", large_cities)

# 添加新列
df['人口密度'] = df['人口'] / df['面积'] * 10000 # 计算人口密度 (人/平方公里)
print("\n添加'人口密度'列后的DataFrame:\n", df)

# 分组聚合 (虽然这个小例子分组意义不大,但展示用法)
# grouped = df.groupby('是否省会')['人口'].mean()
# print("\n按是否省会分组计算人口均值:\n", grouped)

3. Matplotlib

是什么?

Matplotlib 是一个用于创建出版质量图表的 Python 库。它可以生成各种静态、动态、交互式的图表,是数据可视化的重要工具。

核心概念

  • Figure (图形对象): 是最高层级的容器,包含了所有的绘图元素(如 Axes, Title, Labels)。一个 Figure 可以包含一个或多个 Axes。

  • Axes (坐标系/子图): 是绘图区域,实际的数据图形(如折线、散点、柱状图等)就是绘制在 Axes 上。每个 Axes 都有 x 轴、y 轴(对于二维图表)以及标题、标签等。通常通过 plt.subplots()fig.add_subplot() 创建。

  • Artist (艺术家): 图形上的所有可见元素都是 Artist 对象,例如 Line2D(线)、Text(文本)、Patch(矩形、圆形等)、Collection(散点集合)等。

两种使用接口

  1. Pyplot 接口 ( matplotlib.pyplot ) 基于状态机,提供了一系列函数(如 plot(), scatter(), xlabel(), title(), show() )。使用简单快捷,适合快速生成图表,但对于复杂图表控制稍显不足。

  2. 面向对象 (Object-Oriented) 接口: 通过创建 Figure 和 Axes 对象,然后调用对象的方法来创建和修改图表。更灵活和强大,适合定制复杂图表。这是 Matplotlib 推荐的用法。

主要特点和功能

  1. 丰富的图表类型: 支持绘制折线图 ( plot )、散点图 ( scatter )、柱状图 ( bar )、直方图 ( hist )、饼图 ( pie )、箱线图 ( boxplot )、热力图 ( imshow ) 等多种图表。

  2. 高度可定制: 可以精细地控制图表的每一个元素,包括线条样式、颜色、标记、文本、标题、坐标轴刻度、图例等。

  3. 多子图布局: 可以在同一个 Figure 中创建多个 Axes,方便进行多图对比展示 ( plt.subplots() )。

  4. 导出多种格式: 可以将图表保存为多种文件格式,如 PNG、JPG、SVG、PDF 等。

  5. 集成性好: 可以直接使用 NumPy 数组和 Pandas DataFrame/Series 进行绘图。

为什么重要?

  • 可视化: 将数据转化为图形,帮助人们更直观地理解数据的分布、趋势、关系和模式。

  • 沟通: 精美的图表是数据分析结果的重要呈现方式,便于与他人沟通分析结果。

  • 探索性分析 (EDA): 在数据分析的早期阶段,快速生成图表有助于发现数据中的异常和规律。

简单示例 (使用 Pyplot 接口)


import matplotlib.pyplot as plt
import numpy as np
import pandas as pd # 展示与Pandas的结合

# 绘制简单的折线图
x = np.linspace(0, 10, 100) # 生成0到10之间100个点的数组
y = np.sin(x) # 计算每个点的sin值
plt.figure(figsize=(8, 4)) # 创建一个图形对象,并设置大小
plt.plot(x, y, label='sin(x)', color='blue', linestyle='--') # 绘制折线图
plt.xlabel('x 轴') # 设置x轴标签
plt.ylabel('y 轴') # 设置y轴标签
plt.title('简单的 sin(x) 函数图') # 设置图表标题
plt.legend() # 显示图例
plt.grid(True) # 显示网格线
plt.show() # 显示图表

# 绘制散点图
x_scatter = np.random.rand(50) # 生成50个随机x坐标
y_scatter = np.random.rand(50) # 生成50个随机y坐标
colors = np.random.rand(50) # 随机颜色
sizes = 1000 * np.random.rand(50) # 随机大小
plt.figure(figsize=(6, 6))
plt.scatter(x_scatter, y_scatter, c=colors, s=sizes, alpha=0.5) # alpha设置透明度
plt.title('随机散点图')
plt.xlabel('X 值')
plt.ylabel('Y 值')
plt.colorbar(label='颜色深浅') # 添加颜色条
plt.show()

# 使用 Pandas 数据绘制柱状图 (Pandas调用Matplotlib)
df_cities = pd.DataFrame({
    '城市': ['北京', '上海', '广州', '深圳'],
    '人口': [2154, 2487, 1530, 1756]
})
plt.figure(figsize=(7, 5))
df_cities.plot(x='城市', y='人口', kind='bar', legend=False) # 直接调用DataFrame的plot方法
plt.title('城市人口柱状图')
plt.xlabel('城市')
plt.ylabel('人口 (万人)')
plt.xticks(rotation=0) # x轴标签不旋转
plt.show()

三者如何协同工作?

在典型的数据分析流程中,这三个库经常按以下方式配合使用:

  1. Pandas: 用于加载、清洗、处理和组织数据。将原始数据读入 Pandas DataFrame,进行缺失值处理、数据转换、格式调整、合并等操作。

  2. NumPy: 在 Pandas 内部被广泛使用,也用于执行一些更底层的数值计算、数组操作或数学函数应用。当你需要在 DataFrame/Series 的数据上执行高性能的数组运算时,NumPy 的功能会非常有用。

  3. Matplotlib: 用于将处理后的数据进行可视化。你可以直接使用 Matplotlib 的函数(如 plt.plot(), plt.scatter() )传入 NumPy 数组或 Pandas Series/DataFrame 中的数据列进行绘制。或者,更常见的是直接调用 Pandas DataFrame/Series 内置的 .plot() 方法,这些方法实际上是调用了 Matplotlib 进行绘图,使用起来更加方便。

总结

  • NumPy: 提供高性能的多维数组和基础数值运算能力,是底层计算核心。

  • Pandas: 提供易用的数据结构(DataFrame, Series)和丰富的数据处理、清洗、转换功能,是数据整理和分析的主要工具。

  • Matplotlib: 提供强大的数据可视化能力,用于将数据结果呈现为图表。

这三个库共同构成了 Python 数据分析的强大生态系统,掌握它们是进行高效数据分析的关键。