云计算百科
云计算领域专业知识百科平台

大模型学习之数据分析——面向大模型的Pandas 与 Matplotlib基础

摘要:Pandas 是 Python 数据处理的核心库,提供 Series(一维)和 DataFrame(二维)两种数据结构,支持数据读写(CSV、JSON)、索引选择(loc/iloc)、数据清洗(去重、缺失值)、数据合并(merge/concat)、分组聚合(groupby)等完整的数据处理能力。在大模型应用中,Pandas 贯穿评测集构建、模型输出解析、badcase 分析、结果统计全流程,是数据处理的首选工具。

Matplotlib 是 Python 最基础的可视化库,大模型角色只需简要了解,掌握折线图(看 loss 曲线)、直方图(看数据分布)、柱状图(看类别分布)三种最常用的图即可。通过 df.plot() 一行出图,配合 savefig() 保存实验记录,足以满足日常分析需求。

两者结合,构成大模型应用开发中「数据处理 + 可视化」的完整工具链:Pandas 负责数据清洗与分析,Matplotlib 负责快速可视化,共同支撑评测、调试、实验记录等核心工作流。

目录

二、pandas基础

2.1 Pandas 介绍

2.1.1 Pandas 是什么

2.1.2 Pandas 数据结构

2.1.3 为什么大模型角色要学 Pandas

2.2 Series 与 DataFrame 基础

2.2.1 创建对象

2.2.2 索引与选择

2.2.3 赋值与新增列

2.2.4 排序

2.2.5 重命名与列操作

2.2.6 类型转换 astype

2.3 数据读写(数据进出)

2.3.1 模型输出 → DataFrame

2.3.2 CSV

2.3.3 JSON

2.3.4 MySQL(了解)

2.3.5 与 NumPy / PyTorch 互转

2.4 DataFrame 运算

2.4.1 逻辑运算

2.4.2 统计运算

2.4.2.1 describe / mean / std / sum

2.4.2.2 value_counts

2.5 数据处理

2.5.1 去重 drop_duplicates

2.5.2 添加 / 删除列

2.5.3 缺失值处理

2.5.4 数据合并

2.5.4.1 merge(键连接)

2.5.5 数据分组与聚合

2.5.6 文本处理

2.5.7 随机采样

2.5.8 时间序列基础

2.5.9 透视表与交叉表(了解)

2.6 综合实战案例

2.6.1 模型输出解析(JSON → DataFrame)

2.6.2 评测集统计(准确率、badcase)

2.6.3 数据清洗与导出

三、Matplotlib 入门(简要了解)            

3.1 Matplotlib 介绍

3.1.1 Matplotlib 是什么

3.1.2 为什么大模型角色只需简要了解

3.2 大模型场景下最常用的图

3.2.1 loss / accuracy 曲线(折线图)

3.2.2 数据分布(直方图)

3.2.3 类别分布(柱状图)

3.2.4 散点图(了解)

3.2.5 图表选择指南(了解)

3.3 基础绘图功能

3.3.1 与 pandas 联动 df.plot() 

3.3.2 与 NumPy 数组直接绘图 

3.3.3 pyplot 风格 plt.plot / scatter / hist

3.3.4 标题、坐标轴标签、图例

3.3.5 保存图片 savefig


二、pandas基础

2.1 Pandas 介绍

2.1.1 Pandas 是什么

Pandas 是 Python 最流行的数据分析库,核心是两种数据结构:Series(一维)和 DataFrame(二维)。它建立在 NumPy 之上,提供了更强大的数据操作能力。

一句话理解: Pandas 让 Python 能像 Excel 一样处理表格数据,但功能更强大、更灵活。

核心能力:

能力说明
数据读写 CSV、JSON、Excel、MySQL 等
数据清洗 缺失值、去重、类型转换
数据筛选 条件筛选、排序、分组
数据聚合 groupby、透视表
数据合并 merge、concat

2.1.2 Pandas 数据结构

2.1.2.1 Series 对象

Series 是 Pandas 的一维数据结构,由索引(index)和值(values)组成。可以理解为"带标签的一维数组"。

2.1.2.2 DataFrame 对象

DataFrame 是 Pandas 的二维数据结构,由行索引(index)和列索引(columns)组成。可以理解为"带标签的二维表格"。

2.1.2.3 与 NumPy 的核心区别
维度NumPyPandas
维度 多维数组 一维 Series、二维 DataFrame
索引 隐式整数索引 支持标签索引
类型 要求统一 dtype 列间可不同 dtype
缺失值 nan(仅浮点) None / NaN / NaT
列名 无 有列名
应用 数值计算 数据处理

2.1.3 为什么大模型角色要学 Pandas

Pandas 是大模型应用开发中数据处理的核心工具,贯穿评测、清洗、分析全流程。

应用场景

场景说明
数据清洗 清洗训练数据、评测数据
评测集 构建、管理评测集
badcase 分析模型错误案例
模型输出解析 JSON → DataFrame,批量分析
结果统计 准确率、召回率、分布统计

2.2 Series 与 DataFrame 基础

2.2.1 创建对象

Pandas 支持从多种数据源创建 Series 和 DataFrame。

# 创建 Series 和 DataFrame

import pandas as pd
import numpy as np

# ===== Series =====
# 从列表
s1 = pd.Series([1, 2, 3, 4, 5])

# 从字典
s2 = pd.Series({"a": 1, "b": 2, "c": 3})

# 从 ndarray
s3 = pd.Series(np.array([10, 20, 30]))

# 指定索引
s4 = pd.Series([1, 2, 3], index=["x", "y", "z"])

print(f"从列表:\\n{s1}")
print(f"\\n从字典:\\n{s2}")
print(f"\\n指定索引:\\n{s4}")

# ===== DataFrame =====
# 从字典(最常见)
df1 = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"age": [25, 30, 28],
"city": ["杭州", "上海", "北京"]
})

# 从列表的字典
df2 = pd.DataFrame([
{"name": "张三", "age": 25},
{"name": "李四", "age": 30},
])

# 从 ndarray
df3 = pd.DataFrame(np.array([[1, 2], [3, 4]]), columns=["A", "B"])

print(f"\\nDataFrame 从字典:\\n{df1}")
print(f"\\nDataFrame 从列表的字典:\\n{df2}")
print(f"\\nDataFrame 从 ndarray:\\n{df3}")

方法说明:

方法说明
pd.Series() 创建 Series。参数为数据,index 指定索引
pd.DataFrame() 创建 DataFrame。参数为字典、列表、ndarray,columns 指定列名

说明:

  • Series 从列表、字典、ndarray 创建

  • DataFrame 从字典(最常见)、列表的字典、ndarray 创建

  • columns 指定列名

2.2.2 索引与选择

2.2.2.1 loc(标签索引)

loc 基于标签索引,使用行索引名和列名。

# loc:标签索引

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"age": [25, 30, 28],
"city": ["杭州", "上海", "北京"]
}, index=["a", "b", "c"])

# 取单行
print(f"df.loc['a']:\\n{df.loc['a']}")

# 取单列
print(f"\\ndf.loc[:, 'name']:\\n{df.loc[:, 'name']}")

# 取单值
print(f"\\ndf.loc['a', 'name']:{df.loc['a', 'name']}")

# 取多行多列
print(f"\\ndf.loc['a':'b', ['name', 'age']]:\\n{df.loc['a':'b', ['name', 'age']]}")

方法说明:

语法说明
df.loc[行标签] 取行
df.loc[:, 列标签] 取列
df.loc[行标签, 列标签] 取单值
df.loc[行标签列表, 列标签列表] 取多行多列

说明:

  • loc 基于标签

  • 切片 'a':'b' 包含右端

2.2.2.2 iloc(位置索引)

iloc 基于位置索引,使用整数位置。

# iloc:位置索引

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"age": [25, 30, 28],
"city": ["杭州", "上海", "北京"]
})

# 取单行
print(f"df.iloc[0]:\\n{df.iloc[0]}")

# 取单列
print(f"\\ndf.iloc[:, 0]:\\n{df.iloc[:, 0]}")

# 取单值
print(f"\\ndf.iloc[0, 0]:{df.iloc[0, 0]}")

# 取多行多列
print(f"\\ndf.iloc[0:2, 0:2]:\\n{df.iloc[0:2, 0:2]}")

方法说明:

语法说明
df.iloc[行位置] 取行
df.iloc[:, 列位置] 取列
df.iloc[行位置, 列位置] 取单值
df.iloc[行位置切片, 列位置切片] 取多行多列

说明:

  • iloc 基于位置

  • 切片 0:2 不含右端

2.2.2.3 布尔索引

布尔索引用条件表达式筛选数据,返回满足条件的行。

# 布尔索引

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"age": [25, 30, 28],
"city": ["杭州", "上海", "北京"]
})

# 单条件
result = df[df["age"] > 26]
print(f"age > 26:\\n{result}")

# 多条件
result = df[(df["age"] > 26) & (df["city"] == "上海")]
print(f"\\nage > 26 且 city == 上海:\\n{result}")

# isin
result = df[df["city"].isin(["杭州", "北京"])]
print(f"\\ncity in [杭州, 北京]:\\n{result}")

方法说明:

语法说明
df[条件] 布尔索引筛选
df[条件1 & 条件2] 多条件,用 & 且加括号
df[列].isin(列表) 判断是否在列表中

说明:

  • 布尔索引返回满足条件的行

  • 多条件用 &、|,不能用 and、or

2.2.2.4 易错点:loc 含右端,iloc 不含右端

# 错误:以为 loc 和 iloc 切片行为一致

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"age": [25, 30, 28]
}, index=["a", "b", "c"])

# loc:含右端
print(f"loc['a':'b']:\\n{df.loc['a':'b']}") # 包含 a 和 b

# iloc:不含右端
print(f"\\niloc[0:2]:\\n{df.iloc[0:2]}") # 包含 0 和 1,不含 2

说明:

索引方式切片行为
loc 含右端
iloc 不含右端
2.2.2.5 易错点:链式赋值 SettingWithCopy

# 错误:链式赋值

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"age": [25, 30, 28]
})

# 链式赋值:先筛选,再赋值
# df[df["age"] > 26]["age"] = 100 # SettingWithCopyWarning

# 正确:用 .loc 一步到位
df.loc[df["age"] > 26, "age"] = 100
print(df)

说明:

  • 链式赋值可能修改的是副本,而非原 DataFrame

  • 用 .loc[条件, 列] = 值 一步到位

  • 避免链式赋值

2.2.3 赋值与新增列

Pandas 支持直接赋值新增列、修改列值、条件赋值。

# 赋值与新增列

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"age": [25, 30, 28]
})

# ===== 新增列:常量 =====
df["city"] = "杭州"
print(f"新增常量列:\\n{df}")

# ===== 新增列:计算 =====
df["age_plus_10"] = df["age"] + 10
print(f"\\n新增计算列:\\n{df}")

# ===== 新增列:条件赋值 =====
df["is_adult"] = df["age"] >= 18
print(f"\\n新增条件列:\\n{df}")

# ===== 修改列值 =====
df["age"] = df["age"] + 1
print(f"\\n修改列值:\\n{df}")

# ===== 删除列 =====
df = df.drop(columns=["age_plus_10"])
print(f"\\n删除列:\\n{df}")

方法说明:

方法说明
df["新列"] = 值 新增列或修改列
df.drop(columns=[…]) 删除列。columns 指定列名

说明:

  • 新增列直接赋值

  • 条件赋值用布尔表达式

  • drop 返回新 DataFrame,不修改原数据

2.2.4 排序

2.2.4.1 sort_values / sort_index [L3]

# 排序

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"age": [25, 30, 28]
}, index=["c", "a", "b"])

# 按值排序:默认升序
print(f"按 age 升序:\\n{df.sort_values('age')}")

# 降序
print(f"\\n按 age 降序:\\n{df.sort_values('age', ascending=False)}")

# 按索引排序
print(f"\\n按索引排序:\\n{df.sort_index()}")

方法说明:

方法说明
df.sort_values() 按值排序。by 指定列,ascending 控制升降序
df.sort_index() 按索引排序

说明:

  • 默认升序

  • 返回新 DataFrame,不修改原数据

2.2.4.2 易错点:默认不原地,需 inplace 或重新赋值 [L2]

# 错误:以为排序会修改原 DataFrame

import pandas as pd

df = pd.DataFrame({"age": [30, 25, 28]})

df.sort_values("age") # 返回新 DataFrame,原 df 未变
print(f"原 df:\\n{df}") # 顺序未变

# 正确:重新赋值
df = df.sort_values("age")
print(f"\\n重新赋值后:\\n{df}")

# 或使用 inplace
df.sort_values("age", inplace=True)

说明:

  • sort_values 默认返回新 DataFrame

  • 需重新赋值或 inplace=True

  • 推荐重新赋值

2.2.5 重命名与列操作

# 重命名与列操作

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四"],
"age": [25, 30]
})

# 方式一:rename
df1 = df.rename(columns={"name": "姓名", "age": "年龄"})
print(f"rename:\\n{df1}")

# 方式二:直接赋值 columns
df2 = df.copy()
df2.columns = ["姓名", "年龄"]
print(f"\\n直接赋值 columns:\\n{df2}")

# 查看列名
print(f"\\n列名:{df.columns.tolist()}")

方法说明:

方法说明
df.rename() 重命名。columns 指定列映射,index 指定索引映射
df.columns 列名,可赋值修改

说明:

  • rename 返回新 DataFrame

  • columns 直接赋值修改

2.2.6 类型转换 astype

astype() 用于转换数据类型,返回新 DataFrame。

# 类型转换 astype

import pandas as pd

df = pd.DataFrame({
"age": ["25", "30", "28"],
"score": [85.5, 92.3, 78.8]
})

print(f"原始类型:\\n{df.dtypes}")

# 字符串转整数
df["age"] = df["age"].astype(int)
print(f"\\n转换后类型:\\n{df.dtypes}")

# 浮点转整数
df["score_int"] = df["score"].astype(int)
print(f"\\n转换后:\\n{df}")

# 转为 category(节省内存)
df["age_cat"] = df["age"].astype("category")
print(f"\\ncategory 类型:{df['age_cat'].dtype}")

方法说明:

方法说明
df[列].astype() 转换列类型。参数为目标类型,如 int、float、str、category

说明:

  • astype 返回新 Series,需重新赋值

  • 浮点转整数会截断小数

  • category 类型节省内存

2.3 数据读写(数据进出)

2.3.1 模型输出 → DataFrame

大模型输出通常为 JSON 格式(列表的字典、嵌套字典),需转为 DataFrame 进行分析。这是大模型评测、badcase 分析的第一步。

2.3.2 CSV

CSV 是最常用的数据存储格式,Pandas 提供 read_csv 和 to_csv 读写。

# CSV 读写

import pandas as pd

# ===== 写入 CSV =====
df = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"age": [25, 30, 28],
"city": ["杭州", "上海", "北京"]
})

df.to_csv("data.csv", index=False, encoding="utf-8")

# ===== 读取 CSV =====
df2 = pd.read_csv("data.csv", encoding="utf-8")
print(f"\\n读取结果:\\n{df2}")

方法说明:

方法说明
df.to_csv() 写入 CSV。index=False 不写索引,encoding 指定编码
pd.read_csv() 读取 CSV。encoding 指定编码,sep 指定分隔符

常用参数:

参数说明
index 是否写入索引,默认 True
encoding 编码,常用 utf-8、gbk
sep 分隔符,默认 ,
header 是否有表头,默认 0

2.3.3 JSON

JSON 是 API 和模型输出的常见格式,Pandas 支持读写。

# JSON 读写

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四"],
"age": [25, 30]
})

# 写入 JSON
df.to_json("data.json", orient="records", force_ascii=False)

# 读取 JSON
df2 = pd.read_json("data.json")
print(f"\\n读取结果:\\n{df2}")

方法说明:

方法说明
df.to_json() 写入 JSON。orient 指定方向,force_ascii=False 保留中文
pd.read_json() 读取 JSON

orient 参数:

值说明
"records" 列表的字典(推荐)
"index" 字典的字典
"columns" 列导向
"values" 仅值

2.3.4 MySQL(了解)

Pandas 可以读写 MySQL 数据库,需配合 sqlalchemy 或 pymysql。

实际项目中使用较少,了解即可。

方法说明:

方法说明
pd.read_sql() 读取 SQL 查询结果
df.to_sql() 写入数据库表

2.3.5 与 NumPy / PyTorch 互转

2.3.5.1 .values / .to_numpy()

DataFrame 和 Series 可以转为 NumPy 数组,用于数值计算。

# 与 NumPy 互转

import pandas as pd
import numpy as np

df = pd.DataFrame({
"age": [25, 30, 28],
"score": [85.5, 92.3, 78.8]
})

# 方式一:.values
arr1 = df.values
print(f".values:\\n{arr1}")
print(f"类型:{type(arr1)},dtype:{arr1.dtype}")

# 方式二:.to_numpy()(推荐)
arr2 = df.to_numpy()
print(f"\\n.to_numpy():\\n{arr2}")

# Series 转 NumPy
s = df["age"]
arr3 = s.to_numpy()
print(f"\\nSeries.to_numpy():{arr3}")

方法说明:

方法说明
df.values 返回 NumPy 数组(旧版,不推荐)
df.to_numpy() 返回 NumPy 数组(推荐)。dtype 指定类型

说明:

  • .to_numpy() 是推荐方法,.values 是旧版

  • 混合 dtype 的 DataFrame 转为 NumPy 会统一为 object 或 float

2.3.5.2 与 PyTorch 对接前的 dtype 注意

Pandas → NumPy → PyTorch 是大模型数据处理的常见链路。关键注意:NumPy 默认 float64,PyTorch 默认 float32。

# 与 PyTorch 对接

import pandas as pd
import numpy as np
import torch

df = pd.DataFrame({
"age": [25, 30, 28],
"score": [85.5, 92.3, 78.8]
})

# 问题:默认 float64
arr = df.to_numpy()
tensor = torch.from_numpy(arr)
print(f"默认 dtype:{tensor.dtype}") # torch.float64

# 正确:显式转 float32
arr = df.to_numpy(dtype=np.float32)
tensor = torch.from_numpy(arr)
print(f"转换后 dtype:{tensor.dtype}") # torch.float32

方法说明:

方法说明
df.to_numpy(dtype=…) 转为指定 dtype 的 NumPy 数组
torch.from_numpy() NumPy 数组转 PyTorch 张量(共享内存)

说明:

  • NumPy 默认 float64,PyTorch 默认 float32

  • 对接前需显式转换

  • 大模型中统一使用 float32

2.4 DataFrame 运算

2.4.1 逻辑运算

Pandas 的逻辑运算用于组合多个条件,返回布尔 Series。

运算符说明
& 与(and)
| 或(or)
~ 非(not)

注意: 必须用 &、|、~,不能用 and、or、not;且每个条件必须加括号。

# 逻辑运算

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "王五", "赵六"],
"age": [25, 30, 28, 35],
"city": ["杭州", "上海", "北京", "上海"]
})

# 与:&
result = df[(df["age"] > 26) & (df["city"] == "上海")]
# result = df[(df["age"] > 26) and (df["city"] == "上海")] # ValueError
print(f"age > 26 且 city == 上海:\\n{result}")

# 或:|
result = df[(df["age"] > 30) | (df["city"] == "杭州")]
print(f"\\nage > 30 或 city == 杭州:\\n{result}")

# 非:~
result = df[~(df["city"] == "上海")]
print(f"\\ncity != 上海:\\n{result}")

说明:

  • & 与、| 或、~ 非

  • 每个条件必须加括号

  • 不能用 and、or、not

2.4.2 统计运算

2.4.2.1 describe / mean / std / sum

Pandas 提供常用统计函数,可对整表或指定列计算。

# 统计运算

import pandas as pd

df = pd.DataFrame({
"age": [25, 30, 28, 35, 22],
"score": [85.5, 92.3, 78.8, 88.0, 95.5]
})

# describe:综合统计
print(f"describe:\\n{df.describe()}")

# 单列统计
print(f"\\nage 均值:{df['age'].mean():.2f}")
print(f"age 标准差:{df['age'].std():.2f}")
print(f"age 求和:{df['age'].sum()}")

# 按列统计
print(f"\\n各列均值:\\n{df.mean()}")

方法说明:

方法说明
df.describe() 综合统计,返回计数、均值、标准差、分位数
df.mean() 均值
df.std() 标准差
df.sum() 求和

说明:

  • describe 一次性输出多个统计量

  • 单列统计用 df["列"].方法()

  • 按列统计用 df.方法()

2.4.2.2 value_counts

value_counts() 用于统计每个值出现的次数,常用于分类数据分布分析。

# value_counts

import pandas as pd

df = pd.DataFrame({
"city": ["杭州", "上海", "北京", "上海", "杭州", "上海"]
})

# 统计频次
print(f"value_counts:\\n{df['city'].value_counts()}")

# 转为比例
print(f"\\n比例:\\n{df['city'].value_counts(normalize=True)}")

方法说明:

方法说明
Series.value_counts() 统计每个值的出现次数。normalize=True 返回比例

说明:

  • 默认按频次降序

  • normalize=True 返回比例

  • 常用于分类数据分布分析

2.5 数据处理

2.5.1 去重 drop_duplicates

drop_duplicates() 用于去除重复行,可指定列或全部列。

# 去重

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "张三", "王五", "李四"],
"city": ["杭州", "北京", "杭州", "北京", "上海"]
})

# 全部列去重
print(f"原始数据:\\n{df}")
print(f"\\n全部列去重:\\n{df.drop_duplicates()}") # 行Series对象完全相同才会去除

# 按指定列去重(保留第一条)
print(f"\\n按 name 去重:\\n{df.drop_duplicates(subset=['name'])}") # 指定列对应元素相同就去除

# 按指定列去重(保留最后一条)
print(f"\\n按 name 去重(保留最后):\\n{df.drop_duplicates(subset=['name'], keep='last')}")

方法说明:

参数说明
subset 指定列,默认全部列
keep 'first'(默认)保留第一条,'last' 保留最后一条,False 全部删除

说明:

  • 默认全部列去重

  • subset 指定去重列

  • keep 控制保留哪条

2.5.2 添加 / 删除列

# 添加 / 删除列

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"age": [25, 30, 28]
})

# assign:新增列
df1 = df.assign(age_plus_10=df["age"] + 10)
print(f"assign 新增列:\\n{df1}")

# 链式 assign
df2 = df.assign(
age_plus_10=df["age"] + 10,
is_adult=df["age"] >= 18
)
print(f"\\n链式 assign:\\n{df2}")

# drop:删除列
df3 = df.drop(columns=["age"])
print(f"\\ndrop 删除列:\\n{df3}")

# drop:删除行
df4 = df.drop(index=[0, 2])
print(f"\\ndrop 删除行:\\n{df4}")

方法说明:

方法说明
df.assign() 新增列。参数为 列名=值,返回新 DataFrame
df.drop() 删除列或行。columns 指定列,index 指定行

说明:

  • assign 返回新 DataFrame,可链式调用

  • drop 返回新 DataFrame

2.5.3 缺失值处理

# 缺失值处理

import pandas as pd
import numpy as np

df = pd.DataFrame({
"name": ["张三", "李四", "王五", "赵六"],
"age": [25, np.nan, 28, 35],
"score": [85, 92, np.nan, 88]
})

print(f"原始数据:\\n{df}")

# isnull:判断缺失
print(f"\\n是否缺失:\\n{df.isnull()}")

# 统计缺失数
print(f"\\n缺失数:\\n{df.isnull().sum()}")

# dropna:删除缺失行
print(f"\\n删除缺失行:\\n{df.dropna()}")

# fillna:填充缺失值
print(f"\\n填充 0:\\n{df.fillna(0)}")

# 用均值填充
print(f"\\n用均值填充:\\n{df.fillna(df.mean(numeric_only=True))}")

print(f"原始数据:\\n{df}") # 不会修改原数据

方法说明:

方法说明
df.isnull() 判断是否缺失,返回布尔 DataFrame
df.dropna() 删除缺失值。axis 指定轴,how 指定条件
df.fillna() 填充缺失值。参数为填充值

说明:

  • isnull() 返回布尔 DataFrame

  • dropna() 删除含缺失值的行

  • fillna() 填充缺失值

  • 不会修改原数据,返回新的DataFrame对象

2.5.4 数据合并

2.5.4.1 merge(键连接)

merge 用于按键连接两个 DataFrame,类似 SQL 的 JOIN。

# merge:键连接

import pandas as pd

df1 = pd.DataFrame({
"id": [1, 2, 3],
"name": ["张三", "李四", "王五"]
})

df2 = pd.DataFrame({
"id": [2, 3, 4],
"score": [85, 92, 78]
})

# 内连接:只保留两表都有的键
inner = pd.merge(df1, df2, on="id", how="inner")
print(f"内连接:\\n{inner}")

# 左连接:保留左表所有键
left = pd.merge(df1, df2, on="id", how="left")
print(f"\\n左连接:\\n{left}")

# 外连接:保留所有键
outer = pd.merge(df1, df2, on="id", how="outer")
print(f"\\n外连接:\\n{outer}")

方法说明:

参数说明
on 连接键,列名
how 连接方式:inner、left、right、outer

说明:

  • inner:只保留两表都有的键

  • left:保留左表所有键

  • outer:保留所有键

2.5.4.2 concat(堆叠)

concat 用于堆叠多个 DataFrame,沿行或列方向。

# concat:堆叠

import pandas as pd

df1 = pd.DataFrame({
"name": ["张三", "李四"],
"age": [25, 30]
})

df2 = pd.DataFrame({
"name": ["王五", "赵六"],
"age": [28, 35]
})

# 沿行堆叠(上下)
row_concat = pd.concat([df1, df2], axis=0, ignore_index=True)
print(f"沿行堆叠:\\n{row_concat}")

# 沿列堆叠(左右)
col_concat = pd.concat([df1, df2], axis=1)
print(f"\\n沿列堆叠:\\n{col_concat}")

方法说明:

参数说明
axis 0 沿行堆叠,1 沿列堆叠
ignore_index 是否重置索引

说明:

  • axis=0 上下堆叠

  • axis=1 左右堆叠

  • ignore_index=True 重置索引

2.5.5 数据分组与聚合

2.5.5.1 groupby 基础

groupby 是 Pandas 最强大的功能之一,用于按某个键分组,然后对每组做聚合运算。

核心流程: 拆分(split)→ 应用(apply)→ 合并(combine)

# groupby 基础

import pandas as pd

df = pd.DataFrame({
"city": ["杭州", "上海", "杭州", "上海", "北京", "杭州"],
"name": ["张三", "李四", "王五", "赵六", "钱七", "孙八"],
"score": [85, 92, 78, 88, 95, 90]
})

# 按 city 分组,求 score 均值
grouped = df.groupby("city")["score"].mean()
print(f"按 city 分组求均值:\\n{grouped}")

# 按 city 分组,求多个统计量
print(f"\\n按 city 分组,多个统计量:\\n{df.groupby('city')['score'].agg(['mean', 'max', 'min'])}")

# 按 city 分组,统计人数
print(f"\\n按 city 分组,统计人数:\\n{df.groupby('city').size()}")

方法说明:

方法说明
df.groupby("列") 按列分组,返回 GroupBy 对象
.agg([…]) 多个聚合函数
.size() 统计每组数量

说明:

  • groupby 返回 GroupBy 对象,需接聚合函数

  • agg 可一次计算多个统计量

  • size 统计每组行数

2.5.5.2 agg 多聚合 

agg 用于对分组数据同时应用多个聚合函数。

# agg 多聚合

import pandas as pd

df = pd.DataFrame({
"city": ["杭州", "上海", "杭州", "上海", "北京"],
"score": [85, 92, 78, 88, 95],
"age": [25, 30, 28, 35, 22]
})

# 多个聚合函数
result = df.groupby("city").agg({
"score": ["mean", "max", "min"],
"age": "mean"
})
print(f"多聚合:\\n{result}")

# 命名聚合(推荐)
result2 = df.groupby("city").agg(
score_mean=("score", "mean"),
score_max=("score", "max"),
age_mean=("age", "mean")
)
print(f"\\n命名聚合:\\n{result2}")

方法说明:

参数说明
agg(字典) 对不同列应用不同聚合函数
agg(命名元组) 命名聚合,推荐

说明:

  • 字典形式:{"列": ["函数1", "函数2"]}

  • 命名聚合:新列名=("列", "函数")

  • 命名聚合更清晰

2.5.5.3 reset_index 

groupby 的结果索引是分组键,用 reset_index() 可将分组键转为列。

# reset_index

import pandas as pd

df = pd.DataFrame({
"city": ["杭州", "上海", "杭州", "上海", "北京"],
"score": [85, 92, 78, 88, 95]
})

# groupby 结果:索引是 city
grouped = df.groupby("city")["score"].mean()
print(f"未 reset_index:\\n{grouped}")
print(f"索引:{grouped.index.tolist()}")

# reset_index:索引转为列
grouped_reset = grouped.reset_index()
print(f"\\nreset_index 后:\\n{grouped_reset}")
print(f"列名:{grouped_reset.columns.tolist()}")

方法说明:

方法说明
.reset_index() 将索引转为列,返回新 DataFrame

说明:

  • groupby 结果索引是分组键

  • reset_index() 将索引转为列

  • 方便后续处理

2.5.6 文本处理

2.5.6.1 str 访问器

str 访问器用于对字符串列进行向量化操作,如大小写、替换、切分。

# str 访问器

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四", "王五"],
"email": ["ZhangSan@example.com", "LiSi@test.com", "WangWu@demo.com"]
})

# 大写
print(f"大写:\\n{df['email'].str.upper()}")

# 小写
print(f"\\n小写:\\n{df['email'].str.lower()}")

# 包含判断
print(f"\\n包含 example:\\n{df['email'].str.contains('example')}")

# 替换
print(f"\\n替换:\\n{df['email'].str.replace('.com', '.cn')}")

# 切分
print(f"\\n切分:\\n{df['email'].str.split('@')}")

方法说明:

方法说明
.str.upper() 转大写
.str.lower() 转小写
.str.contains() 包含判断
.str.replace() 替换
.str.split() 切分

说明:

  • str 访问器用于字符串列

  • 向量化操作,比 apply 快

2.5.6.2 apply / map / applymap 区分
方法作用对象说明
apply 行/列 对每行或每列应用函数
map Series 对每个元素应用函数
applymap DataFrame 对每个元素应用函数

# apply / map / applymap

import pandas as pd

df = pd.DataFrame({
"name": ["张三", "李四"],
"score": [85, 92]
})

# apply:对列应用
print(f"apply 对列:\\n{df[['score']].apply(lambda x: x.max())}")

# map:对 Series 每个元素
print(f"\\nmap:\\n{df['name'].map(lambda x: f'学生-{x}')}")

# applymap:对 DataFrame 每个元素
print(f"\\napplymap:\\n{df.applymap(lambda x: str(x)+"test")}")

说明:

  • apply 作用于行/列

  • map 作用于 Series 元素

  • applymap 作用于 DataFrame 元素

2.5.6.3 拆分列 split / str.split

str.split() 用于拆分字符串列,可配合 expand=True 拆为多列。

# 拆分列

import pandas as pd

df = pd.DataFrame({
"info": ["张三-25-杭州", "李四-30-上海", "王五-28-北京"]
})

# 拆分为多列
split_df = df["info"].str.split("-", expand=True)
split_df.columns = ["name", "age", "city"]
print(f"拆分后:\\n{split_df}")

# 合并到原 DataFrame
df = pd.concat([df, split_df], axis=1)
print(f"\\n合并后:\\n{df}")

方法说明:

参数说明
str.split(sep) 按分隔符拆分
expand=True 拆为多列

说明: expand=True 拆为多列,否则返回列表。

2.5.7 随机采样

sample() 用于随机采样,常用于数据集划分、抽样分析。

# 随机采样

import pandas as pd

df = pd.DataFrame({
"id": range(1, 11),
"score": [85, 92, 78, 88, 95, 90, 82, 87, 91, 86]
})

# 随机取 3 条
print(f"随机取 3 条:\\n{df.sample(n=3, random_state=42)}")

# 随机取 30%
print(f"\\n随机取 30%:\\n{df.sample(frac=0.3, random_state=42)}")

方法说明:

参数说明
n 采样数量
frac 采样比例
random_state 随机种子,保证可复现

说明: random_state 保证结果可复现。

2.5.8 时间序列基础

to_datetime() 用于将字符串转为时间类型,dt 访问器用于提取时间属性。

# 时间序列基础

import pandas as pd

df = pd.DataFrame({
"date": ["2024-01-15", "2024-02-20", "2024-03-25"],
"score": [85, 92, 78]
})

# 转为时间类型
df["date"] = pd.to_datetime(df["date"])
print(f"转换后类型:{df['date'].dtype}")

# dt 访问器
df["year"] = df["date"].dt.year
df["month"] = df["date"].dt.month
df["day"] = df["date"].dt.day
print(f"\\n提取年月日:\\n{df}")

方法说明:

方法说明
pd.to_datetime() 转为时间类型
.dt.year 提取年份
.dt.month 提取月份
.dt.day 提取日

2.5.9 透视表与交叉表(了解)

概念说明类比
透视表(pivot_table) 对数据进行多维汇总,可指定值列、行、列和聚合函数 类似 Excel 数据透视表
交叉表(crosstab) 统计两个分类变量的频次,是透视表的特例 类似列联表

2.6 综合实战案例

2.6.1 模型输出解析(JSON → DataFrame)

调用本地 Ollama 模型,获取 JSON 输出,解析为 DataFrame。这是大模型应用开发的第一步。

# 模型输出解析:JSON → DataFrame

import httpx
import json
import pandas as pd

# 调用 Ollama
def call_ollama(prompt):
"""调用本地 Ollama 模型"""
response = httpx.post(
"http://localhost:11434/v1/chat/completions",
headers={"Authorization": "Bearer ollama"},
json={
"model": "qwen2.5:1.5b",
"messages": [{"role": "user", "content": prompt}],
"stream": False
},
timeout=60
)
return response.json()["choices"][0]["message"]["content"]

# 批量调用
prompts = [
"用一句话介绍 Python",
"用一句话介绍 Java",
"用一句话介绍 Go",
]

results = []
for i, prompt in enumerate(prompts):
output = call_ollama(prompt)
results.append({
"id": i + 1,
"prompt": prompt,
"output": output,
"length": len(output)
})

# 转为 DataFrame
df = pd.DataFrame(results)
print(f"模型输出:\\n{df}")

# 保存
df.to_csv("model_outputs.csv", index=False, encoding="utf-8")
print("\\n已保存 model_outputs.csv")

方法说明:

方法说明
httpx.post() 发送 POST 请求。json 参数传递请求体
response.json() 解析 JSON 响应
pd.DataFrame() 从列表的字典创建 DataFrame
df.to_csv() 保存为 CSV。index=False 不写索引

说明:

  • 调用 Ollama 获取模型输出

  • 批量调用,收集结果

  • 转为 DataFrame,保存

2.6.2 评测集统计(准确率、badcase)

构建评测集,调用模型,统计准确率,筛选 badcase。这是大模型评测的核心流程。

# 评测集统计

import httpx
import json
import pandas as pd

def call_ollama(prompt):
"""调用本地 Ollama 模型"""
response = httpx.post(
"http://localhost:11434/v1/chat/completions",
headers={"Authorization": "Bearer ollama"},
json={
"model": "qwen2.5:1.5b",
"messages": [
{"role": "system", "content": "你是一个分类助手,只回答类别名称。"},
{"role": "user", "content": prompt}
],
"stream": False
},
timeout=60
)
return response.json()["choices"][0]["message"]["content"].strip()

# 评测集
test_cases = [
{"id": 1, "text": "今天天气真好", "label": "积极"},
{"id": 2, "text": "这个产品太差了", "label": "消极"},
{"id": 3, "text": "我喜欢这个电影", "label": "积极"},
{"id": 4, "text": "服务态度很差", "label": "消极"},
{"id": 5, "text": "一般般吧", "label": "中性"},
]

# 批量评测
for case in test_cases:
prompt = f"判断以下文本的情感(积极/消极/中性):{case['text']}"
case["pred"] = call_ollama(prompt)

# 转为 DataFrame
df = pd.DataFrame(test_cases)
print(f"评测结果:\\n{df}")

# 统计准确率
df["correct"] = df["pred"] == df["label"]
accuracy = df["correct"].mean()
print(f"\\n准确率:{accuracy:.2%}")

# 筛选 badcase
badcases = df[~df["correct"]]
print(f"\\nbadcase:\\n{badcases}")

方法说明:

方法说明
df["correct"] = df["pred"] == df["label"] 新增布尔列
df["correct"].mean() 计算准确率
df[~df["correct"]] 筛选 badcase

说明:

  • 批量调用模型,收集预测

  • 统计准确率

  • 筛选 badcase 分析

2.6.3 数据清洗与导出

对模型输出进行数据清洗(去重、缺失值、文本处理),然后导出。

# 数据清洗与导出

import pandas as pd
import numpy as np

# 模拟模型输出(含脏数据)
df = pd.DataFrame({
"id": [1, 2, 3, 4, 5, 5],
"prompt": ["介绍Python", "介绍Java", "介绍Go", None, "介绍C++", "介绍C++"],
"output": ["Python是一种…", "Java是一种…", None, "Go是一种…", "C++是一种…", "C++是一种…"],
"score": [0.95, 0.87, 0.92, 0.88, np.nan, 0.88]
})

print(f"原始数据:\\n{df}")
print(f"\\n缺失值:\\n{df.isnull().sum()}")

# 去重
df = df.drop_duplicates(subset=["prompt"])
print(f"\\n去重后:\\n{df}")

# 删除缺失值
df = df.dropna(subset=["prompt", "output"])
print(f"\\n删除缺失后:\\n{df}")

# 填充缺失值
df["score"] = df["score"].fillna(df["score"].mean())
print(f"\\n填充后:\\n{df}")

# 文本处理:截断输出
df["output_short"] = df["output"].str[:20]
print(f"\\n截断后:\\n{df}")

# 导出
df.to_csv("cleaned_data.csv", index=False, encoding="utf-8")
df.to_json("cleaned_data.json", orient="records", force_ascii=False)
print("\\n已导出 cleaned_data.csv 和 cleaned_data.json")

方法说明:

方法说明
df.drop_duplicates() 去重
df.dropna() 删除缺失值
df.fillna() 填充缺失值
df["列"].str[:20] 文本截断
df.to_csv() 导出 CSV
df.to_json() 导出 JSON

说明:

  • 去重、删除缺失、填充缺失

  • 文本处理

  • 导出为 CSV / JSON

三、Matplotlib 入门(简要了解)

3.1 Matplotlib 介绍

3.1.1 Matplotlib 是什么

Matplotlib 是 Python 最基础、最常用的数据可视化库,用于绘制各种图表(折线图、直方图、柱状图等)。

一句话理解: Matplotlib 让 Python 能像 Excel 一样画图,但更灵活、更可定制。

3.1.2 为什么大模型角色只需简要了解

大模型应用开发中,可视化不是核心工作,但需要快速出图辅助分析。

大模型场景下的典型需求

需求图表类型说明
看 loss 曲线 折线图 观察训练是否收敛
看数据分布 直方图 观察数据分布是否均匀
看类别分布 柱状图 观察类别是否平衡
记录实验 保存图片 保存到实验目录,便于对比

3.2 大模型场景下最常用的图

3.2.1 loss / accuracy 曲线(折线图)

折线图用于展示随时间变化的趋势,是大模型训练中最常用的图。通过 loss 曲线判断训练是否收敛、是否过拟合。

场景说明
看 loss 曲线 判断训练是否收敛
看 accuracy 曲线 判断模型是否提升
对比多次实验 对比不同超参数的训练效果
  • X 轴:epoch(训练轮次)

  • Y 轴:loss(损失值)

  • 判断:loss 持续下降并趋于平稳 → 收敛

  • 判断:loss 先降后升 → 过拟合

3.2.2 数据分布(直方图)

直方图用于展示数据的分布情况,观察数据是否均匀、是否偏斜。

场景说明
看数据分布 观察数据是否均匀
看长尾分布 观察是否存在长尾
数据清洗前 判断是否需要归一化
  • X 轴:数据值(分箱)

  • Y 轴:频次

  • 判断:中间高两边低 → 正态分布

  • 判断:偏左或偏右 → 偏斜分布

3.2.3 类别分布(柱状图)

柱状图用于展示不同类别的数量对比,观察类别是否平衡。

场景说明
看类别分布 观察类别是否平衡
badcase 统计 统计各类 badcase 数量
评测结果 统计各标签的准确率
  • X 轴:类别

  • Y 轴:数量

  • 判断:柱子高度差异大 → 类别不平衡

  • 应用:badcase 统计、评测结果分析

3.2.4 散点图(了解)

散点图用于展示两个变量之间的关系,观察是否存在相关性。

场景说明
看相关性 观察两个变量是否相关
看聚类 观察数据是否分群
异常值检测 观察是否有离群点
  • X 轴:变量 1

  • Y 轴:变量 2

  • 判断:点呈上升趋势 → 正相关

  • 判断:点分散 → 无相关

说明: 散点图在大模型场景中较少用,了解即可。

3.2.5 图表选择指南(了解)

根据分析目的选择合适的图表类型。

分析目的推荐图表示例
看趋势 折线图 loss 曲线
看分布 直方图 数据分布
看对比 柱状图 类别分布
看关系 散点图 相关性

大模型场景速查

需求图表
训练是否收敛 折线图
数据是否均匀 直方图
类别是否平衡 柱状图
变量是否相关 散点图

说明: 大模型角色主要用折线图、直方图、柱状图,散点图了解即可。

3.3 基础绘图功能

3.3.1 与 pandas 联动 df.plot() 

Pandas 内置 plot() 方法,基于 Matplotlib,可一行代码出图,是最便捷的方式。

# 与 pandas 联动 df.plot()

import pandas as pd
import matplotlib.pyplot as plt

# 模拟训练日志
df = pd.DataFrame({
"epoch": [1, 2, 3, 4, 5, 6, 7, 8],
"loss": [1.0, 0.8, 0.6, 0.5, 0.4, 0.35, 0.33, 0.32],
"accuracy": [0.5, 0.6, 0.7, 0.75, 0.8, 0.83, 0.85, 0.86]
})

# 折线图:loss 曲线
df.plot(x="epoch", y="loss", title="Loss Curve")
plt.savefig("loss_curve.png")
plt.show()

# 多条曲线
df.plot(x="epoch", y=["loss", "accuracy"], title="Training Metrics")
plt.show()

方法说明:

参数说明
x X 轴列名
y Y 轴列名(可为列表)
kind 图表类型:line、bar、hist、scatter
title 图表标题

说明:

  • df.plot() 一行出图

  • kind 指定图表类型

  • 返回 Axes 对象,可继续定制

3.3.2 与 NumPy 数组直接绘图 

Matplotlib 可直接接收 NumPy 数组,无需转 DataFrame。

# 与 NumPy 数组直接绘图

import numpy as np
import matplotlib.pyplot as plt

# 生成数据
x = np.linspace(0, 10, 100)
y = np.sin(x)

# 直接绘图
plt.plot(x, y)
plt.title("Sin Wave")
plt.show()

# 多条曲线
y2 = np.cos(x)
plt.plot(x, y, label="sin")
plt.plot(x, y2, label="cos")
plt.legend()
plt.show()

方法说明:

参数说明
x, y 数据数组
label 曲线标签,用于图例

说明: Matplotlib 可直接接收 NumPy 数组。

3.3.3 pyplot 风格 plt.plot / scatter / hist

pyplot 是 Matplotlib 的函数式接口,提供 plt.plot、plt.scatter、plt.hist 等快捷方法。

# pyplot 风格

import numpy as np
import matplotlib.pyplot as plt

# ===== 折线图 =====
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.title("Line Plot")
plt.show()

# ===== 散点图 =====
x = np.random.rand(50)
y = np.random.rand(50)
plt.scatter(x, y)
plt.title("Scatter Plot")
plt.show()

# ===== 直方图 =====
data = np.random.randn(1000)
plt.hist(data, bins=30)
plt.title("Histogram")
plt.show()

方法说明:

方法说明
plt.plot() 折线图
plt.scatter() 散点图
plt.hist() 直方图。bins 指定分箱数

说明:

  • plt.plot 折线图

  • plt.scatter 散点图

  • plt.hist 直方图

3.3.4 标题、坐标轴标签、图例

为图表添加标题、坐标轴标签、图例,使图表更清晰。

# 标题、坐标轴标签、图例

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)

plt.plot(x, np.sin(x), label="sin")
plt.plot(x, np.cos(x), label="cos")

# 标题
plt.title("test")

# 坐标轴标签
plt.xlabel("x")
plt.ylabel("y")

# 图例
plt.legend()

plt.show()

方法说明:

方法说明
plt.title() 设置标题
plt.xlabel() 设置 X 轴标签
plt.ylabel() 设置 Y 轴标签
plt.legend() 显示图例

说明:

  • title 标题

  • xlabel / ylabel 坐标轴标签

  • legend 图例,需在 plot 时指定 label

3.3.5 保存图片 savefig

savefig() 用于保存图片到文件,常用于记录实验。

# 保存图片

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)

plt.plot(x, np.sin(x))
plt.title("Sin Wave")

# 保存图片
plt.savefig("sin_wave.png", dpi=150, bbox_inches="tight")
print("已保存 sin_wave.png")

方法说明:

参数说明
fname 文件名,支持 PNG、JPG、PDF
dpi 分辨率,默认 100
bbox_inches "tight" 去除多余空白

说明:

  • 支持多种格式:PNG、JPG、PDF、SVG

  • dpi 控制清晰度

  • bbox_inches="tight" 去除空白

赞(0)
未经允许不得转载:网硕互联帮助中心 » 大模型学习之数据分析——面向大模型的Pandas 与 Matplotlib基础
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!