【零基础学AI】第 15 章——数据可视化与探索
第 15 章 数据可视化与探索文章目录第 15 章 数据可视化与探索 关于《AI 零基础 36 讲》先问一个能用现有字段回答的问题把运行环境和输入先核对一遍问题一已知时长落在哪些区间问题二不同标签完成了多少条问题三时长与完成状态怎样对应没有相关系数时别补成零从特别大的数回到原始记录把图和分析一起保存留一道独立练习资料来源第 14 章把八行学习记录清洗成了五行。表格已经可以读问题还没问完。已知时长通常是多少两个标签的完成情况怎样花了更多时间的记录在这份表里是不是更常显示完成这一章用同一份数据回答这三个问题分别生成直方图、柱状图和散点图。你会得到一份已经执行的分析 Notebook、三张可发布的原创图表以及一份保留统计范围的分析报告。前置条件是读完第 14 章能读取 CSV、选择行列并处理缺失值。下面始终使用上一章清洗结果的快照不修改原表。 关于《AI 零基础 36 讲》零基础也能开始学 AI《AI 零基础 36 讲》是一套面向初学者的 AI 入门教程。课程从认识和使用 AI 开始逐步学习Python、数据处理、机器学习与深度学习再进入大模型应用开发最后完成个人知识库助手的综合实践。本篇是正式讲解文章通过具体例子、原创图示和操作结果讲清概念。涉及编程的章节提供可运行代码方便你边读边试。读完以后动手检验建议按专栏顺序学习并完成对应的课后训练检查自己能否独立运用本章知识。博客专栏《AI 零基础 36 讲》先问一个能用现有字段回答的问题本章表格有记录 ID、主题、完成状态、分钟数与标签。没有测验分数也没有日期。用它回答“学得久是不是考得好”就会缺少结果字段把 source_row 当日期又会把文件行号误读成学习时间。我们先把问题收在已有字段的范围内。时长分布看 minutes不同标签的完成情况看 tag 与 done时长与完成状态的关系则要两列配对。先确认问题需要哪些字段再决定画什么图这样图形才有可核对的内容。当前问题使用字段图形纳入的记录已知时长落在哪些区间minutes直方图时长已知的三条不同标签完成了多少条tag、done柱状图全部五条时长与完成状态怎样对应minutes、done散点图两项都已知的三条探索性分析就是先查看现有数据的数量、分布和关系再找值得继续检查的问题。它可以帮助发现漏填、单位不一致或某条特别大的数值。探索结果需要带着数据范围阅读不能把看见的形状直接扩展成普遍结论。把运行环境和输入先核对一遍本章新增 Matplotlib 3.10.7继续使用 NumPy 2.3.5 与 Pandas 3.0.1。在本章目录运行下面的命令。python-m venv.venv.venv\Scripts\python.exe-m pip install-r requirements.txt.venv\Scripts\python.exe examples/explore_records.py第三条命令会生成全部图表与统计文件。第一次可以先运行让自己知道完整结果长什么样再回到下面逐步理解。macOS 与 Linux 使用.venv/bin/python。先读数据核对总行数与缺失数量。importpandasaspd framepd.read_csv(data/learning_records.csv,dtype{done:boolean,minutes:Float64})print(len(frame))print(frame[minutes].notna().sum())print(frame[minutes].isna().sum())结果是 5、3、2。notna 表示当前值不是缺失isna 表示当前值缺失。两个数量相加等于五条总记录这个检查很小却能解释后面为什么某些图只有三个点。两条未知时长仍然保留在表里。L03 的状态是完成L04 的状态是未完成。它们可以参与完成数量统计不能参与时长均值或时长散点。一个字段缺失不会自动让同一行的其他字段失效。问题一已知时长落在哪些区间直方图把一个数值字段分成连续区间再数每个区间有多少项。它适合观察时长的分布。柱子的位置对应数值范围宽度也带着区间含义。我们按十分钟分一组边界为 0、10、20、30、40、50。先算数量再画图。importnumpyasnpimportpandasaspd framepd.read_csv(data/learning_records.csv,dtype{minutes:Float64})valuesframe[minutes].dropna().to_numpy(dtypefloat)counts,edgesnp.histogram(values,bins[0,10,20,30,40,50])print(values.tolist())print(counts.tolist())print(values.mean())print(np.median(values))已知值为 20、15、40区间计数是[0, 1, 1, 0, 1]。平均值是 25中位数是 20。中位数就是把值排序后取中间位置本例排序为 15、20、40中间那个值是 20。直方图区间一般左端包含、右端不包含最后一个区间包含右端。15 落在 10 到 20 之前20 落在 20 到 30 之前40 落在 40 到 50 这一组。改变区间宽度柱子的形状也会改变比较两张分布图时要先看边界是否相同。图的纵轴是记录条数没有画成百分比也没有使用密度。密度会按样本数量和区间宽度调整柱高它与每个区间有几条记录不同。入门阶段先看计数图能直接把柱高和原表对起来。制作这张图的核心动作如下。importpandasaspdfromplot_styleimportconfigure_style,new_figure,save_figure configure_style()framepd.read_csv(data/learning_records.csv)fig,axnew_figure(已知学习时长的分布,学习时长分钟,记录数量条,虚构教学数据只使用三条已知时长记录。)ax.hist(frame[minutes].dropna(),bins[0,10,20,30,40,50])save_figure(fig,results,practice-histogram)print(已保存 practice-histogram.png 与 SVG)这段可以在本章目录运行辅助模块在 examples 中。若单独另建脚本把它放在 examples 目录或一并复制 plot_style.py。hist 执行分组计数标题和轴标签让读者知道数字单位save_figure 把图存下来。现在只有三个已知数图能准确展示它们落在哪些区间。不能凭三根柱子宣布学习时长符合某种总体分布。平均值高于中位数也只说明当前三项的数值结构40 把平均值向上拉了一些。问题二不同标签完成了多少条柱状图适合比较类别。python 和 ai 是两个标签先按标签分组再统计各组记录数和完成数。importpandasaspd framepd.read_csv(data/learning_records.csv,dtype{done:boolean,minutes:Float64})groupsframe.groupby(tag).agg(records(record_id,size),completed(done,sum))groups[completion_rate]groups[completed]/groups[records]print(groups.to_dict(index))groupby 把标签相同的记录放在一组agg 指定每组怎样汇总。size 数全部行布尔列的 sum 把 True 计为一、False 计为零所以得到完成条数。python 组有三条、完成两条比例是 2/3约 66.7%。ai 组有两条、完成一条比例是 1/2也就是 50%。比例的分母必须是本组全部记录不能因为要画时长图而提前删掉未知时长行。图中每个类别并排放两根柱子一根表示全部记录一根表示完成记录。纵轴从零开始数量差异可以直接看。完成比例写在完成柱附近它和柱高的“条数”使用不同单位图里已经明确标注。ai 与 python 的完成比例确实不同但数据分别只有两条和三条。每组多加入一条记录比例就可能明显变化。标签还对应不同学习主题难度没有控制所以这里仅描述这五条记录不据此判断哪类知识更容易学。问题三时长与完成状态怎样对应散点图把两个字段放在横纵轴上每条有效记录画一个点。横轴使用分钟数完成状态先编码为 0 与 10 表示未完成1 表示完成。这个编码只表示两个状态不代表完成质量高低。importpandasaspd framepd.read_csv(data/learning_records.csv,dtype{done:boolean,minutes:Float64})pairedframe.dropna(subset[minutes,done])print(paired[[record_id,minutes,done]].to_dict(records))pointspd.DataFrame({minutes:paired[minutes].astype(float),done_code:paired[done].astype(int)})print(points.corr().loc[minutes,done_code])三个点分别对应 L01 的 20 分钟且完成、L02 的 15 分钟且未完成、L05 的 40 分钟且完成。相关系数约为 0.655。相关系数在这里衡量两个数值字段的线性关联程度。能定义时它介于 -1 与 1 之间正号表示在当前样本中较大的分钟数倾向于对应较大的完成编码负号表示相反方向。接近零表示线性关联较弱复杂关系仍可能存在。纵轴只有两个取值所以散点只能排在两条水平位置上这是状态编码本身造成的。我们没有给状态人为加小数来美化图也没有把三个点连成趋势线。点旁边保留记录 ID可以回到原表逐条检查。这个正相关值不能说明“多学五分钟就会完成”。记录涉及不同主题还可能有任务难度、原有基础等差异当前数据没有提供这些信息。样本又只有三条其中两条完成补上未知时长后数值关系也可能变化。没有相关系数时别补成零两列中任意一列没有变化相关系数就不能按通常方式定义。比如三个完成状态全部为 True完成编码没有差异时长都一样也会出现相同问题。只有一对记录时同样不足以计算通常的 Pearson 相关系数。本章统计函数会检查有效点数和各列不同值数量无法计算时返回 None并在 JSON 中保存为 null。零表示算出来的线性关联接近零null 表示这一项没有可定义的结果两种情况不能混为一谈。还要注意配对。不能分别删去横纵轴的缺失值再假定两组数组仍然对应同一批记录。本章先在整张表上筛选有效行然后从同一份 paired 表取得两列。横纵长度不一致的实际报错与修复输出见 error-samples.md。从特别大的数回到原始记录这份表里 40 比 15 与 20 大但没有足够证据把它判为录错。先查看 L05 的来源核对单位、字段和任务再决定是否需要处理。看到离其他点远的数字可以把它作为待查线索删除要有根据。如果把单位“秒”误写成“分钟”数值也可能仍在 0 到 1440 的合法范围内。第 14 章的类型与范围检查能发现一部分问题业务含义需要另外核对。本章保留记录 ID、来源行号与分钟数质量标记就是为了让这些检查能回到具体记录。绘图范围也可能藏掉数据。当前直方图边界只到 50未来加入 80 分钟的记录就要扩展边界。统计程序会检查所有已知值是否都被分箱计数落在范围之外时明确报错不静默少画一条。把图和分析一起保存explore_records.py 输出三张 1600 × 1000 PNG 和三份保留文本的 SVG同时写入 analysis_summary.json 与 group_summary.csv。JSON 记录参与分析的数量、分箱边界、分组结果、散点配对与相关系数还保存输入文件的校验值方便重复运行时确认数据未换。使用 exploration.ipynb 可以逐格查看同样的统计和图。安装 requirements-notebook.txt 后在第 9 章的编辑器中选择本章环境从头运行所有单元格。交付 Notebook 已有真实内核输出独立分析结论见 analysis-report.md。如果中文变成方框先核对绘图字体。本章辅助模块优先寻找系统中的微软雅黑或 Noto Sans CJK SC 等中文字体找不到时会提示安装或修改候选名字。留一道独立练习把直方图区间换成 0、20、40、60先在纸上判断 15、20、40 各在哪一组再算区间计数。预期三个区间各有一项不能把 20 同时算进左右两组。随后分别对两个标签统计缺失分钟数预期各有一项。完整答案见 【零基础学AI】第 15 章课后练习与答案。下一章会用具体数字和图形解释方差、概率与梯度下降继续练习怎样从一次计算里读出含义。资料来源【零基础学AI】第 15 章课后练习与答案Matplotlib 直方图与分箱Matplotlib 柱状图Matplotlib 散点图Pandas 相关系数与缺失处理