Python机器学习常用库快速精通

python在机器学习领域的有很多经典的第三方库,本文主要是介绍Nump、Pandas、Matplotlib、Seaborn、与Sklearn五个库的基础使用

一 Numpy库

Python 科学计算的基石和性能引擎。

1.1 核心概念:ndarray

NumPy的核心是同质数据的多维数组(所有元素类型相同),相比Python列表具有:

  • 内存效率高:连续内存存储

  • 运算速度快:向量化操作,无需Python循环

  • 功能丰富:广播、矩阵运算、随机数等

python 复制代码
import numpy as np

# 基础属性
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.ndim)      # 维度数:2
print(arr.shape)     # 形状:(2, 3)
print(arr.dtype)     # 数据类型:int64
print(arr.size)      # 元素总数:6

1.2 数组创建方法

python 复制代码
# 从Python结构转换
np.array([1, 2, 3])                    # 列表转数组
np.array([(1, 2), (3, 4)], dtype=float) # 指定类型

# 内置创建函数
np.zeros((3, 4))        # 3×4零矩阵
np.ones((2, 3, 4))      # 2×3×4全1数组(三维)
np.eye(3)               # 3×3单位矩阵
np.full((2, 2), 7)      # 填充特定值

# 序列生成
np.arange(0, 10, 2)     # [0, 2, 4, 6, 8],步长为2
np.linspace(0, 1, 5)    # [0, 0.25, 0.5, 0.75, 1],5个等间距点

# 随机数组
np.random.rand(3, 3)           # 0-1均匀分布
np.random.randn(3, 3)          # 标准正态分布
np.random.randint(1, 10, (3,3)) # 随机整数
np.random.seed(42)             # 设置随机种子保证可复现

1.3数据类型(dtype)

python 复制代码
# 常见类型
np.array([1, 2, 3], dtype=np.int32)    # 32位整数
np.array([1.0, 2.0], dtype=np.float64) # 64位浮点(默认)
np.array([True, False], dtype=np.bool_) # 布尔型

# 类型转换
arr.astype(np.float32)  # 转换数据类型

1.4 索引与切片

python 复制代码
arr = np.arange(10).reshape(2, 5)  # 2×5数组

# 基础索引
arr[0, 1]          # 0行1列元素:1
arr[0][1]          # 同上(但不建议,效率较低)

# 切片(重要:切片是视图view,非副本)
arr[:, 1:3]        # 所有行,1-2列
arr[::-1]          # 行逆序

# 布尔索引(筛选)
arr[arr > 5]       # 所有大于5的元素(一维结果)
arr[(arr > 2) & (arr < 8)]  # 多条件(&|, ~分别代表与或非)

# 花式索引(整数数组索引)
arr[[0, 1], [2, 3]]  # 取(0,2)和(1,3)元素 → [2, 8]
arr[:, [0, 2, 4]]    # 取第0,2,4列

# 获取副本(避免修改原数组)
arr[0:2, 0:2].copy()

1.5 数组运算与广播

向量化运算是NumPy的核心优势:

python 复制代码
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

# 元素级运算
a + b          # [5, 7, 9]
a * b          # [4, 10, 18](逐元素乘,非矩阵乘)
a ** 2         # [1, 4, 9]
np.sqrt(a)     # 开方

# 矩阵乘法
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
A @ B          # 或 np.dot(A, B),矩阵乘法

# 广播机制(Broadcasting)
# 标量广播
a + 10         # [11, 12, 13]

# 维度广播(自动扩展较小数组)
matrix = np.ones((3, 3))
vector = np.arange(3)          # [0, 1, 2]
matrix + vector                # 每行加vector,结果为[[1,2,3], [1,2,3], [1,2,3]]

# 广播规则:从后向前比较维度,相等或其中一个为1时可广播

1.6 常用数学与统计函数

python 复制代码
arr = np.random.randn(4, 5)

# 基础统计
arr.sum()          # 总和
arr.mean()         # 均值
arr.std()          # 标准差
arr.var()          # 方差
arr.min()          # 最小值
arr.max()          # 最大值
arr.argmin()       # 最小值索引(扁平化后)
arr.argmax()       # 最大值索引

# 轴参数(axis)关键概念
arr.sum(axis=0)    # 按列求和(压缩行,结果形状(5,))
arr.sum(axis=1)    # 按行求和(压缩列,结果形状(4,))
arr.mean(axis=0, keepdims=True)  # 保持维度,结果形状(1,5)

# 其他数学函数
np.exp(arr)        # 指数
np.log(arr)        # 自然对数
np.sin(arr)        # 三角函数
np.ceil(arr)       # 向上取整
np.floor(arr)      # 向下取整
np.clip(arr, -1, 1) # 限制在[-1,1]区间

1.7 数组形状操作

python 复制代码
arr = np.arange(12)  # [0..11]

# 重塑(reshape,返回视图或副本)
arr.reshape(3, 4)          # 3×4数组
arr.reshape(3, -1)         # -1自动计算该维度大小
arr.reshape(2, 2, 3)       # 三维数组

# 转置与换轴
arr.T                      # 转置(二维)
arr.transpose(1, 0, 2)     # 指定轴顺序
arr.swapaxes(0, 1)         # 交换两个轴

# 扁平化
arr.flatten()              # 返回副本(一维)
arr.ravel()                # 返回视图(高效,修改会影响原数组)

# 增删维度
arr[np.newaxis, :]         # 增加轴,形状(1, 12)
arr[:, np.newaxis]         # 形状(12, 1)
np.squeeze(arr)            # 移除长度为1的轴

1.8 数组合并与分割

python 复制代码
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])

# 合并
np.vstack((a, b))          # 垂直堆叠(行增加)
np.hstack((a, b.T))        # 水平堆叠(列增加)
np.concatenate([a, b], axis=0)  # 指定轴连接
np.stack([a, a], axis=0)   # 在新轴上堆叠,结果(2,2,2)

# 分割
np.split(arr, 3, axis=0)   # 等分为3份
np.array_split(arr, 3)     # 不等分(更常用)
np.hsplit(arr, 2)          # 水平分割
np.vsplit(arr, 2)          # 垂直分割

1.9 线性代数(np.linalg)

python 复制代码
A = np.array([[3, 1], [1, 2]])
b = np.array([9, 8])

# 核心运算
np.linalg.inv(A)           # 逆矩阵
np.linalg.det(A)           # 行列式
np.linalg.matrix_rank(A)   # 矩阵秩
np.linalg.solve(A, b)      # 解线性方程组 Ax = b

# 分解与特征
eigenvalues, eigenvectors = np.linalg.eig(A)  # 特征值与特征向量
U, S, Vh = np.linalg.svd(A)  # 奇异值分解

# 范数
np.linalg.norm(A)          # Frobenius范数
np.linalg.norm(A, ord=2)   # 谱范数(最大奇异值)

1.10 实用技巧与最佳实践

python 复制代码
# 1. 预分配内存(避免动态扩展)
result = np.empty((1000, 1000))
for i in range(1000):
    result[i] = some_computation()

# 2. 布尔掩码赋值
arr[arr < 0] = 0           # 将所有负数置零(clip的替代)

# 3. 结构化数组(类似数据库记录)
dt = np.dtype([('name', 'U10'), ('age', 'i4'), ('score', 'f4')])
students = np.array([('Alice', 20, 85.5), ('Bob', 21, 92.0)], dtype=dt)
students['name']           # 访问字段

# 4. 内存布局
arr = np.array([[1, 2], [3, 4]], order='C')  # C风格(行优先,默认)
arr = np.array([[1, 2], [3, 4]], order='F')  # Fortran风格(列优先)

# 5. 视图vs副本
view = arr[::2]            # 步长切片,总是视图
copy = arr[::2].copy()     # 显式复制

# 6. 性能优化:避免Python循环,使用向量化
# 慢
result = [np.sin(x) for x in arr]
# 快
result = np.sin(arr)

1.11 实用建议

  1. 忘掉循环,拥抱向量化:养成直接用数组运算思考的习惯,这是用好 NumPy 的关键。

  2. 理解维度 :时刻清楚你的 arr.shape,这是进行复杂操作和广播的基础。

  3. 关注数据类型 :创建数组时,用 dtype 参数(如 np.float32)可节省大量内存。

  4. 作为基石:NumPy 数组是 Pandas(数据分析)、Scikit-learn(机器学习)等所有主流数据科学库的底层数据结构。

python 复制代码
import pandas as pd
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))
values = df.values         # 转为NumPy数组(视图或副本视情况而定)

二 Pandas库

定位表格数据操作的事实标准,R 语言 DataFrame 的 Python 实现。

核心概念DataFrame(二维标签化表格)和 Series(一维标签化数组),自带行列索引。

关键能力

  • 数据 IO:读写 CSV/Excel/SQL/JSON,自动类型推断

  • 数据清洗:缺失值处理(fillna/dropna)、重复值删除、异常值筛选、类型转换

  • 数据变换:透视表(pivot)、长宽格式转换(melt)、分组聚合(groupby)、合并连接(merge/join)

  • 时间序列:日期解析、重采样(resample)、移动窗口计算

典型场景:数据探索性分析(EDA)、特征工程、金融时间序列处理、日志分析。

2.1 核心数据结构

Series(一维带标签数组)

python 复制代码
import pandas as pd
import numpy as np

# 创建
s = pd.Series([1, 3, 5, np.nan, 6, 8], index=['a', 'b', 'c', 'd', 'e', 'f'])
# 自动对齐:基于标签运算,而非位置
s['b']  # 3

DataFrame(二维表格)

python 复制代码
# 从字典创建(最常用)
df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie'],
    'age': [25, 30, 35],
    'salary': [5000, 6000, 7000]
}, index=['a', 'b', 'c'])

# 基础属性
df.shape      # (3, 3) - 行列数
df.columns    # Index(['name', 'age', 'salary'], dtype='object')
df.index      # 行标签
df.dtypes     # 各列数据类型
df.info()     # 详细信息(非空值数量、内存等)
df.describe() # 统计摘要(数值列)

2.2 数据读取与导出

python 复制代码
# 读取(自动推断类型、处理表头)
df = pd.read_csv('data.csv', encoding='utf-8', 
                 sep=',',           # 分隔符
                 header=0,          # 第几行作为列名
                 index_col=0,       # 指定某列为索引
                 parse_dates=['date'], # 解析日期
                 na_values=['NA', 'NULL']) # 识别为NaN的值

# 读取多个sheet
all_sheets = pd.read_excel('example.xlsx', sheet_name=None)
for sheet, data in all_sheets.items():
   print(f"Sheet Name: {sheet}")
   print(data)

# 其他格式
pd.read_excel('data.xlsx', sheet_name='Sheet1')
pd.read_sql('SELECT * FROM table', conn)
pd.read_json('data.json')

# 导出
df.to_csv('output.csv', index=False, encoding='utf-8-sig') # index=False不保存行索引
df.to_excel('output.xlsx', sheet_name='Sheet1')


# 导出多个sheet
df1 = pd.DataFrame({'姓名': ['张三', '李四'], '年龄': [23, 25]})
df2 = pd.DataFrame({'姓名': ['张三', '李四'], '身高': [170, 171]})

with pd.ExcelWriter('multi_sheets.xlsx', engine='xlsxwriter') as writer:
    df1.to_excel(writer, sheet_name='Sheet1', index=False)
    df2.to_excel(writer, sheet_name='Sheet2', index=False)

2.3 索引与选择(核心)

python 复制代码
# 列选择(返回Series或DataFrame)
df['name']          # 单列(Series)
df[['name', 'age']] # 多列(DataFrame)
df.name             # 属性访问(仅当列名是有效标识符时)

# loc(基于标签/名称)
df.loc['a']         # 选择'a'行
df.loc[:, 'name']   # 选择'name'列
df.loc['a':'b', ['name', 'age']]  # 切片(包含'b')
df.loc[df['age'] > 25]  # 布尔索引

# iloc(基于整数位置,左闭右开)
df.iloc[0]          # 第1行
df.iloc[0:2, 0:2]   # 前2行,前2列
df.iloc[[0, 2], [1, 2]] # 特定行列

# at/iat(快速标量访问,比loc/iloc快)
df.at['a', 'name']  # 单个值
df.iat[0, 0]

# 布尔索引(筛选)
df[df['age'] > 25]
df[(df['age'] > 25) & (df['salary'] < 7000)]  # & | ~ 代替 and or not
df.query('age > 25 and salary < 7000')        # 字符串查询(更直观)
df[df['name'].isin(['Alice', 'Bob'])]
df[df['name'].str.contains('li')]             # 字符串匹配

2.4 数据清洗

缺失值处理

python 复制代码
# 检测
df.isnull()       # 或 isna()
df.notnull()
df.isnull().sum() # 每列缺失值数量

# 处理
df.dropna()                    # 删除含NaN的行
df.dropna(subset=['age'])      # 仅当age为NaN时删除
df.dropna(how='all')           # 仅删除全为NaN的行
df.dropna(axis=1)              # 删除含NaN的列

df.fillna(0)                   # 填充0
df['age'].fillna(df['age'].mean()) # 用均值填充
df.fillna(method='ffill')      # 前向填充(用前值)
df.fillna(method='bfill')      # 后向填充

重复值与类型转换

python 复制代码
# 重复值
df.duplicated()                # 标记重复行(除第一次外)
df.duplicated(keep=False)      # 标记所有重复
df.drop_duplicates()           # 删除重复行(保留第一个)
df.drop_duplicates(subset=['name'], keep='last')

# 类型转换
df['age'] = df['age'].astype(int)
df['salary'] = df['salary'].astype(float)
df['category'] = df['category'].astype('category') # 类别型(省内存)
pd.to_numeric(df['col'], errors='coerce') # 无法转换设为NaN
pd.to_datetime(df['date'])     # 转为日期时间

异常值与替换

python 复制代码
# 替换
df['gender'].replace({'M': 'Male', 'F': 'Female'})
df.replace(np.nan, 0)
df['age'].clip(0, 100)         # 限制在0-100之间

# 重命名
df.rename(columns={'old_name': 'new_name'})
df.rename(index={'a': 'row_a'})
df.columns = ['col1', 'col2', 'col3'] # 直接赋值

2.5 数据变换

应用函数

python 复制代码
# apply(沿轴应用函数)
df['age'].apply(lambda x: x + 1)  # Series
df.apply(lambda row: row['age'] * 2, axis=1) # 行操作(axis=1)
df.applymap(str)                  # 逐元素(DataFrame专用,已弃用,用map替代)

# map(Series专用,逐元素映射)
df['gender'].map({'M': 0, 'F': 1})

# apply返回多列
def process(row):
    return pd.Series([row['a']+row['b'], row['a']*row['b']])
df[['sum', 'product']] = df.apply(process, axis=1)

新增/删除列

python 复制代码
# 新增
df['new_col'] = df['age'] * 12
df.insert(1, 'middle_name', 'Unknown') # 在位置1插入

# 删除
del df['temp_col']
df.drop('temp_col', axis=1)      # 返回新DataFrame(原df不变)
df.drop(['col1', 'col2'], axis=1, inplace=True) # 原地修改

排序与排名

python 复制代码
df.sort_values('age', ascending=False)
df.sort_values(['age', 'salary'], ascending=[True, False])
df.sort_index()

df['rank'] = df['salary'].rank(method='dense', ascending=False) # 排名

2.6 . 数据合并与重塑

合并(Merge/Join)

python 复制代码
# merge(类似SQL join)
pd.merge(df1, df2, on='key', how='inner')    # 内连接
pd.merge(df1, df2, left_on='lkey', right_on='rkey', how='left')
pd.merge(df1, df2, on=['key1', 'key2'], how='outer')

# join(基于索引,更便捷)
df1.join(df2, how='left', lsuffix='_left', rsuffix='_right')

# concat(轴向连接)
pd.concat([df1, df2], axis=0)    # 纵向拼接(增加行)
pd.concat([df1, df2], axis=1)    # 横向拼接(增加列)
pd.concat([df1, df2], ignore_index=True) # 重置索引

重塑(Pivot/Melt)

python 复制代码
# pivot(长转宽)
df_pivot = df.pivot(index='date', columns='category', values='sales')

# pivot_table(透视表,支持聚合)
df.pivot_table(values='sales', index='category', 
               columns='region', aggfunc='sum', fill_value=0)

# melt(宽转长)
df_melt = pd.melt(df, id_vars=['id'], value_vars=['A', 'B'], 
                  var_name='variable', value_name='value')

# stack/unstack(层级索引转换)
df.stack()   # 列转行(长格式)
df.unstack() # 行转列(宽格式)

2.7 分组聚合(GroupBy)

python 复制代码
# 基础分组
grouped = df.groupby('department')
grouped.mean()                   # 数值列均值
grouped.agg({'salary': 'mean', 'age': 'max'}) # 多聚合

# 多列分组
df.groupby(['dept', 'gender'])['salary'].agg(['mean', 'sum', 'count'])

# 自定义聚合
df.groupby('dept').agg({
    'salary': lambda x: x.max() - x.min(),  # 极差
    'age': 'mean'
})

# transform(保持原索引,常用于标准化)
df['avg_salary'] = df.groupby('dept')['salary'].transform('mean')

# apply(自定义复杂操作)
def top_n(group, n=3):
    return group.nlargest(n, 'salary')
df.groupby('dept').apply(top_n)

# 过滤
df.groupby('dept').filter(lambda x: x['salary'].mean() > 5000)

2.8 时间序列处理

python 复制代码
# 时间索引
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)

# 时间范围生成
pd.date_range(start='2024-01-01', periods=10, freq='D')   # 日
pd.date_range(start='2024-01-01', periods=12, freq='M')   # 月末
pd.date_range(start='2024-01-01', periods=4, freq='Q')    # 季末

# 重采样(Resample)
df.resample('M').mean()          # 月均值
df.resample('W').sum()           # 周求和
df.resample('D').ffill()         # 日填充

# 移动窗口
df['rolling_mean'] = df['value'].rolling(window=7).mean() # 7日移动平均
df['exp_mean'] = df['value'].ewm(span=7).mean()          # 指数加权平均

# 时间提取
df.index.year
df.index.month
df.index.dayofweek
df.index.to_period('M')          # 转为时期

2.9 高级技巧

多重索引(MultiIndex)

python 复制代码
# 创建
arrays = [[1, 1, 2, 2], ['red', 'blue', 'red', 'blue']]
df_multi = pd.DataFrame({'value': [10, 20, 30, 40]}, 
                        index=pd.MultiIndex.from_arrays(arrays, names=('number', 'color')))

# 访问
df_multi.loc[1]          # 第一层
df_multi.loc[(1, 'red')] # 具体值
df_multi.xs('red', level='color') # cross section

内存优化

python 复制代码
# 降型(Downcast)
df['int_col'] = pd.to_numeric(df['int_col'], downcast='integer')  # int64→int32/int8
df['float_col'] = pd.to_numeric(df['float_col'], downcast='float')

# 类别型
df['category_col'] = df['category_col'].astype('category') # 字符串→类别(省内存)

迭代(避免,尽量用向量化)

python 复制代码
# 慢(逐行Python循环)
for index, row in df.iterrows():
    print(row['name'])

# 快(向量化)
df['new_col'] = df['col1'] + df['col2']

# itertuples(比iterrows快)
for row in df.itertuples():
    print(row.name)

字符串处理(矢量化)

python 复制代码
df['name'].str.lower()
df['name'].str.contains('Alice')
df['name'].str.split(' ').str[0]  # 提取姓
df['name'].str.replace('Mr.', 'Ms.')
df['name'].str.len()
df['name'].str.extract(r'(\d+)')  # 正则提取

1.10与 NumPy/可视化协作

python 复制代码
# 转NumPy(底层数据)
arr = df.values          # 或 to_numpy()
arr = df['col'].to_numpy()

# 快速绘图(基于Matplotlib)
df['age'].plot(kind='hist', bins=20)
df.plot(x='date', y='value', kind='line')
df.boxplot(column='salary', by='department')

# 相关性
df.corr()                # 相关系数矩阵
df.corr()['target'].sort_values(ascending=False) # 与目标变量相关性

1.11 最佳实践

python 复制代码
# 链式操作:使用 df.pipe() 或括号换行保持代码可读性
result = (df
          .query('age > 25')
          .assign(age_month=lambda x: x['age']*12)
          .groupby('dept')
          .agg({'salary': 'mean'}))


# 避免SettingWithCopyWarning:使用 .loc 或 .copy() 明确赋值

# 错误
df[df['age'] > 25]['salary'] = 0
# 正确
df.loc[df['age'] > 25, 'salary'] = 0

# 方法链中赋值:用 assign() 新增列

df = df.assign(age_double=lambda x: x['age'] * 2)

三 Matplotlib

定位 :Python 可视化的底层基础设施,提供类似 MATLAB 的绘图接口。

核心概念Figure(画布)和 Axes(坐标系/子图),面向对象与 pyplot 状态机双接口。

关键能力

  • 基础图表:折线图、散点图、柱状图、直方图、饼图、箱线图

  • 精细控制:坐标轴刻度、图例、标注、颜色映射(colormap)、子图布局(subplot)

  • 多后端支持:Jupyter 内嵌、独立窗口、保存为 PNG/PDF/SVG 矢量图

  • 可扩展性:几乎所有高级可视化库(Seaborn、Plotly 等)都基于它构建

典型场景:出版级论文插图、需要像素级控制的复杂图表、快速数据探查。

3.1 Matplotlib 核心架构:三层理解

理解其架构,能让你从"调用函数"变为"驾驭框架"。

  1. 脚本层(pyplot模块) :我们最常接触的 plt.plot()plt.xlabel() 就属于这一层。它提供一套类似MATLAB的命令式API ,适合快速绘图和交互式环境,它会自动管理当前的图形(Figure)和坐标轴(Axes)。

  2. 艺术家层(Artist对象) :这是Matplotlib的核心抽象层 。一切可见元素(Figure画布、Axes坐标轴、Line2D线条、Text文本)都是一个"艺术家"对象。通过直接操作这些对象,你可以实现像素级的精细控制。

  3. 后端层(Backend) :这是渲染引擎 ,负责将抽象的艺术家对象输出为屏幕上的像素(如 TkAggQt5Agg)或文件(如 PDFPNG)。用户通常无需直接干预。

关键思想 :当你在脚本层调用 plt.plot() 时,底层其实是在当前 Axes 对象上创建了一个 Line2D 艺术家对象,并由后端渲染出来。

复制代码
import matplotlib.pyplot as plt
import numpy as np

# 1. 数据准备 (通常从Pandas DataFrame来)
x = np.linspace(0, 10, 100)
categories = ['A', 'B', 'C', 'D']
values = [25, 40, 30, 35]

# 2. 创建画布和坐标轴 (面向对象风格,更清晰,推荐)
fig, ax = plt.subplots(figsize=(8, 5)) # fig是画布,ax是坐标轴

# 3. 绘制图表(在坐标轴ax上绘制)
ax.plot(x, np.sin(x), label='sin(x)', color='steelblue', linewidth=2) # 折线图
ax.scatter(x[::10], np.sin(x[::10]), color='darkorange', zorder=5) # 散点图(叠加)

# 4. 定制化图表(设置标题、标签、图例等)
ax.set_xlabel('X Axis Label', fontsize=12)
ax.set_ylabel('Y Axis Label', fontsize=12)
ax.set_title('A Professional Plot Example', fontsize=14, fontweight='bold')
ax.legend(frameon=True) # 显示图例
ax.grid(True, linestyle='--', alpha=0.6) # 显示网格

# 5. 保存与展示
fig.tight_layout() # 自动调整子图参数,使之填充整个图像区域
fig.savefig('professional_plot.png', dpi=300, bbox_inches='tight') # 保存高分辨率图片
plt.show()

3.2 基础图表类型(Plot Types)

|------|---------------------|-------------------------|----------------------------------------------------------|
| 图表类型 | 核心方法 | 典型数据分析应用场景 | 关键参数/技巧 |
| 折线图 | ax.plot(x, y) | 时间序列趋势(股价、销量)、连续变量关系。 | marker(标记点)、linestyle(线型)、linewidth(线宽)。 |
| 散点图 | ax.scatter(x, y) | 两个变量间的相关性、数据分布、聚类发现。 | s(点大小)、c(颜色,可赋值为数组以表示第三维)、alpha(透明度)。 |
| 柱状图 | ax.bar(x, height) | 分类数据对比(不同产品销量)、离散数据分布。 | 用 bar 表示并列,用 barh 绘制水平条形图。注意 x 为分类位置。 |
| 直方图 | ax.hist(data, bins) | 单一连续变量的分布情况(年龄分布、成绩分布)。 | bins(箱子数/边界)是关键,决定分布形状的呈现。density=True 可显示概率密度。 |
| 箱线图 | ax.boxplot(data) | 展示数据分布、中位数、异常值,多组数据对比。 | 一眼看出数据的四分位距(IQR)和离群点。 |
| 饼图 | ax.pie(sizes) | 显示各部分占整体的比例(市场份额、预算分配)。 | autopct='%1.1f%%'(显示百分比)、explode(部分突出)、startangle(起始角度)。 |

3.2.1 线图(Line Plot)

复制代码
fig, ax = plt.subplots()
ax.plot(x, y, 
        color='red',           # 颜色:'r', '#FF0000', (1,0,0)
        linestyle='--',        # 线型:'-', '--', '-.', ':'
        linewidth=2,           # 线宽
        marker='o',            # 标记:'o', 's', '^', 'D'
        markersize=8,
        label='Series A')

3.2.2散点图(Scatter Plot)

复制代码
# 基础散点
ax.scatter(x, y, c=colors, s=sizes, alpha=0.6, cmap='viridis')

# 气泡图(三维信息:x, y, size)
ax.scatter(x, y, s=df['population']*0.1, c=df['growth_rate'], 
           cmap='RdYlGn', edgecolors='black', linewidth=0.5)
plt.colorbar(label='Growth Rate')

3.2.3 3 柱状图(Bar Chart)

复制代码
# 垂直柱状图
ax.bar(categories, values, width=0.6, color='steelblue', edgecolor='black')

# 水平柱状图(适合类别多的情况)
ax.barh(categories, values, height=0.5)

# 分组柱状图
x = np.arange(len(categories))
width = 0.35
ax.bar(x - width/2, men_means, width, label='Men')
ax.bar(x + width/2, women_means, width, label='Women')
ax.set_xticks(x)
ax.set_xticklabels(categories)

3.2.4 直方图与密度图(Histogram / KDE)

复制代码
# 直方图
ax.hist(data, bins=30, density=True, alpha=0.7, color='blue', edgecolor='black')

# 叠加核密度估计(需 scipy)
from scipy.stats import gaussian_kde
kde = gaussian_kde(data)
x_range = np.linspace(data.min(), data.max(), 100)
ax.plot(x_range, kde(x_range), 'r-', linewidth=2)

3.2.5 饼图与环形图(Pie Chart)

复制代码
# 基础饼图
wedges, texts, autotexts = ax.pie(sizes, 
                                    labels=labels, 
                                    autopct='%1.1f%%',
                                    startangle=90,
                                    explode=[0, 0.1, 0])  # 突出显示第二块

# 环形图(Donut)
centre_circle = plt.Circle((0,0), 0.70, fc='white')
ax.add_artist(centre_circle)

3.2.6 箱线图与小提琴图(Boxplot / Violin)

复制代码
# 箱线图
bp = ax.boxplot([data1, data2, data3], 
                labels=['A', 'B', 'C'],
                patch_artist=True,  # 填充颜色
                notch=True)         # 凹槽显示中位数置信区间

# 美化箱线图
colors = ['pink', 'lightblue', 'lightgreen']
for patch, color in zip(bp['boxes'], colors):
    patch.set_facecolor(color)

3.3 图形元素精细控制

3.3.1 标题与标签

复制代码
ax.set_title('Main Title', fontsize=16, fontweight='bold', pad=20)
ax.set_xlabel('X Axis', fontsize=12)
ax.set_ylabel('Y Axis', fontsize=12)
ax.text(0.5, 0.5, 'Annotation', transform=ax.transAxes,  # 相对坐标
        ha='center', fontsize=10, bbox=dict(boxstyle='round', facecolor='wheat'))

3.3.2 坐标轴控制

复制代码
# 范围与刻度
ax.set_xlim(0, 10)
ax.set_ylim(-1, 1)
ax.set_xticks(np.arange(0, 11, 2))
ax.set_xticklabels(['Zero', 'Two', 'Four', 'Six', 'Eight', 'Ten'])

# 对数坐标
ax.set_xscale('log')
ax.set_yscale('log')

# 双 Y 轴(次要坐标轴)
ax2 = ax.twinx()
ax2.plot(x, y2, color='red')
ax2.set_ylabel('Secondary Axis', color='red')
ax2.tick_params(axis='y', labelcolor='red')

3.3.3 图例(Legend)

复制代码
ax.legend(loc='upper left',           # 位置:best, upper right, lower left 等
          frameon=True,               # 边框
          fancybox=True,              # 圆角
          shadow=True,
          ncol=2)                     # 多列显示

# 自定义图例(不依赖 label 参数)
from matplotlib.lines import Line2D
custom_lines = [Line2D([0], [0], color='blue', lw=2),
                Line2D([0], [0], color='red', lw=2, linestyle='--')]
ax.legend(custom_lines, ['Line 1', 'Line 2'])

3.3.4注释(Annotation)

复制代码
# 指向特定点的注释
ax.annotate('Peak Value', 
            xy=(peak_x, peak_y),      # 被注释点
            xytext=(peak_x+1, peak_y+0.5),  # 文本位置
            arrowprops=dict(arrowstyle='->', color='red', lw=1.5),
            fontsize=10, color='red')

# 区域阴影
ax.axvspan(xmin=2, xmax=4, alpha=0.2, color='gray', label='Critical Zone')
ax.axhline(y=0.5, color='k', linestyle='--', linewidth=0.5)  # 水平参考线

3.4 颜色与样式系统

3.4.1 颜色映射(Colormap)

复制代码
# 内置 colormap:viridis, plasma, inferno, magma, cividis(感知均匀)
# 定性:tab10, tab20, Set1, Paired
# 连续:Blues, Greens, Oranges
# 发散:RdBu, coolwarm, Spectral

scatter = ax.scatter(x, y, c=z, cmap='viridis')
cbar = plt.colorbar(scatter, ax=ax)
cbar.set_label('Intensity', rotation=270, labelpad=15)

3.4.2 样式表(Style Sheets)

复制代码
# 内置样式
plt.style.use('seaborn-v0_8-whitegrid')  # 白色网格背景
plt.style.use('ggplot')                   # R 风格
plt.style.use('fivethirtyeight')          # 网站风格

# 临时样式
with plt.style.context('dark_background'):
    plt.plot(x, y)

3.4.3 自定义 RC 参数(全局配置)

复制代码
plt.rcParams['font.size'] = 12
plt.rcParams['figure.figsize'] = (10, 6)
plt.rcParams['axes.grid'] = True
plt.rcParams['grid.alpha'] = 0.3

3.5. 子图与复杂布局(Layout)

3.5.1 基础子图(Subplot)

复制代码
# 2×2 子图
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# 遍历绘制
for i, ax in enumerate(axes.flat):
    ax.plot(x, y)
    ax.set_title(f'Subplot {i+1}')

plt.tight_layout()  # 自动调整间距

3.5.2 不规则布局(GridSpec)

复制代码
from matplotlib.gridspec import GridSpec

fig = plt.figure(figsize=(12, 8))
gs = GridSpec(3, 3, figure=fig)

ax1 = fig.add_subplot(gs[0, :])      # 第一行占满
ax2 = fig.add_subplot(gs[1:, 0])     # 第二三行第一列
ax3 = fig.add_subplot(gs[1, 1:])     # 第二行后两列
ax4 = fig.add_subplot(gs[2, 1:])     # 第三行后两列

3.5.3 嵌套子图(Inset Axes)

复制代码
from mpl_toolkits.axes_grid1.inset_locator import inset_axes

# 在主图中添加小图
ax_inset = inset_axes(ax, width="30%", height="30%", loc='upper right')
ax_inset.plot(x, y)
ax_inset.set_xlim(2, 4)  # 放大局部区域
ax_inset.set_ylim(-0.5, 0.5)

3.6. 高级图表类型

3.6.1 误差条与填充区域

复制代码
# 误差条
ax.errorbar(x, y, yerr=error, fmt='o', capsize=5, capthick=2, elinewidth=1)

# 填充区域(置信区间)
ax.fill_between(x, y-std, y+std, alpha=0.3, label='±1 Std Dev')
ax.fill_between(x, 0, y, where=(y > 0), interpolate=True, alpha=0.3)

3.6.2 堆叠图与面积图

复制代码
# 堆叠面积图
ax.stackplot(years, layer1, layer2, layer3, 
             labels=['Layer 1', 'Layer 2', 'Layer 3'],
             colors=['#1f77b4', '#ff7f0e', '#2ca02c'],
             alpha=0.8)

3.6.3 极坐标图(Polar)

复制代码
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
ax.plot(theta, r)
ax.set_rticks([0.5, 1, 1.5])  # 径向刻度

3.6.4 3D 绘图(需 mpl_toolkits)

复制代码
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# 3D 散点
ax.scatter(x, y, z, c=z, cmap='viridis', s=50)

# 3D 曲面
X, Y = np.meshgrid(x, y)
Z = np.sin(X) * np.cos(Y)
ax.plot_surface(X, Y, Z, cmap='coolwarm', alpha=0.8)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

3.7. 数据分析师必备技巧

3.7.1 中文显示解决方案

复制代码
# 方法1:全局设置(推荐)
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 方法2:局部设置
plt.text(0.5, 0.5, '中文', fontproperties='SimHei', fontsize=14)

3.7.2 时间序列绘图(与 Pandas 集成)

复制代码
# Pandas 时间序列自动格式化
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
df['value'].plot(figsize=(12, 6))  # 自动处理时间刻度
plt.gcf().autofmt_xdate()  # 自动旋转日期标签

3.7.3 保存高分辨率图像

复制代码
plt.savefig('figure.png', 
            dpi=300,              # 分辨率(出版级通常300+)
            bbox_inches='tight',  # 去除白边
            facecolor='white',    # 背景色
            format='png')         # 或 'pdf', 'svg', 'eps'(矢量图)

# 透明背景
plt.savefig('figure.png', transparent=True)

3.7.4 性能优化(大数据集)

复制代码
# 降采样(避免百万级点卡死)
mask = np.arange(0, len(x), step=100)  # 每100个点取1个
ax.plot(x[mask], y[mask])

# 使用 Datashader(超大数据集)或简化绘图
ax.plot(x, y, rasterized=True)  # 栅格化(矢量输出时减小文件大小)

3.8 完整实战示例模板

复制代码
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 创建数据
np.random.seed(42)
df = pd.DataFrame({
    '月份': ['1月', '2月', '3月', '4月', '5月'],
    '销售额': [120, 150, 180, 140, 200],
    '利润': [20, 30, 45, 25, 50]
})

# 创建图形(OO 风格)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

# 左图:柱状图
bars = ax1.bar(df['月份'], df['销售额'], color='steelblue', edgecolor='black')
ax1.set_title('月度销售额', fontsize=14, fontweight='bold')
ax1.set_ylabel('金额(万元)')
for bar in bars:
    height = bar.get_height()
    ax1.text(bar.get_x() + bar.get_width()/2., height,
             f'{height}', ha='center', va='bottom')

# 右图:双轴图(销售额 vs 利润率)
ax2_twin = ax2.twinx()
line1 = ax2.plot(df['月份'], df['销售额'], 'o-', color='blue', label='销售额')
line2 = ax2_twin.plot(df['月份'], df['利润'], 's--', color='red', label='利润')

ax2.set_title('销售额与利润趋势', fontsize=14, fontweight='bold')
ax2.set_ylabel('销售额', color='blue')
ax2_twin.set_ylabel('利润', color='red')
ax2.tick_params(axis='y', labelcolor='blue')
ax2_twin.tick_params(axis='y', labelcolor='red')

# 合并图例
lines = line1 + line2
labels = [l.get_label() for l in lines]
ax2.legend(lines, labels, loc='upper left')

plt.tight_layout()
plt.savefig('report_chart.png', dpi=300, bbox_inches='tight')
plt.show()
相关推荐
老徐电商数据笔记2 小时前
BI工具与数据分析平台:数据价值呈现的最后一公里
数据库·数据挖掘·数据分析·bi·bi选型思考
码农水水2 小时前
米哈游Java面试被问:机器学习模型的在线服务和A/B测试
java·开发语言·数据库·spring boot·后端·机器学习·word
产品何同学3 小时前
在线问诊医疗APP如何设计?2套原型拆解与AI生成原型图实战
人工智能·产品经理·健康医疗·在线问诊·app原型·ai生成原型图·医疗app
星爷AG I3 小时前
9-14 知觉整合(AGI基础理论)
人工智能·agi
开源技术3 小时前
Violit: Streamlit杀手,无需全局刷新,构建AI面板
人工智能·python
递归尽头是星辰3 小时前
大模型与向量检索的融合:从核心原理到 Spring AI 落地
人工智能·大模型·向量检索·rag·spring ai·向量库
gihigo19983 小时前
希尔伯特-黄变换(HHT)完整MATLAB实现
人工智能·算法·matlab
我什么都学不会3 小时前
Python练习作业2
开发语言·python
min1811234563 小时前
AI金融风控:智能反欺诈与个性化理财
大数据·人工智能