跳转至

15.4 数据处理与可视化:实例讲解

内容梗概

本课是数据处理与可视化章节的综合实例课(也是作业讲解),基于之前爬虫课爬取的知乎话题回答数据(CSV)完成两个完整案例。案例一:用 Pandas 对回答按作者做分类汇总(groupby + sum),按点赞总数降序排列取前十,再用 Matplotlib 画横向柱状图。案例二:用结巴分词(jieba)的 TF-IDF 接口对 572 篇回答做关键词提取,汇总权重排序后取前 100 个关键词,用 wordcloud 库画词云。老师现场"复现"自己写代码的过程,强调"写一句打印一句"的打印驱动编程方式,并穿插讲解了 TF-IDF 算法的原理。

知识点详解

实例一:知乎话题高赞用户排行(约 00:00 - 25:00)

需求与数据(约 00:00 - 04:00)

  • 数据来源:爬虫课抓取的知乎"Windows 应用软件"话题下 500 多个回答,CSV 含作者 ID、作者名、性别、答案内容、点赞数等列。
  • 目标:把同一作者的多个回答的点赞数累加,找出话题下点赞总数排名前十的用户(高赞用户)。
  • 程序分两个函数:数据处理函数(接受 CSV 文件路径参数)+ 可视化函数。

分类汇总的概念(约 04:00 - 05:45)

  • 类比 Excel 的分类汇总:以某列字段分类,把同类的数值加起来。例如 A=1、B=2、C=3、A=5、C=6 → A 合计 6、B 合计 2、C 合计 9。
  • 对应到数据:用户 A 有两个回答,点赞数 4 和 15,则其总赞数为两者之和。

数据处理流程(约 06:15 - 17:00)

  • 老师强调"写的过程比写出来的代码重要",现场复现"面向打印语句的编程"(打印驱动开发):写一句 print 一句,确认符合预期再往下写;新手不要追求一气呵成几百行,顶多写一个函数测一下。
df = pd.read_csv(file)          # 读入,pandas 自动去掉 CSV 空行,得到 572 行 6 列的 DataFrame
df = df.loc[:, ['author_name', 'voteup_count']]  # loc 切片:取所有行、只保留两列
df = df.groupby('author_name').sum()             # 先分组(groupby 只分组),再 sum 求和(分类汇总)
s = df['voteup_count'].sort_values(ascending=False)  # 取出点赞列,ascending=False 降序排列
top10 = s[:10]                  # 切片取前 10,与列表切片逻辑一致
  • 数据陷阱提醒(约 15:54):爬虫未登录抓取时,开启匿名保护的用户作者名统一显示为"知乎用户",其实是不同人组成的,逻辑上应把"知乎用户"排除掉。

可视化(约 17:00 - 25:00)

  • 用 DataFrame 自带的 plot 接口(Pandas 封装的 Matplotlib 接口)画**横向柱状图**;pandas 官方文档有 visualization 一节,介绍 df.plot 的各种图。
  • 中文乱码问题(约 18:20):Matplotlib 默认字体显示中文是方块乱码,需设置字体:
plt.rcParams['font.sans-serif'] = ['字体名']   # rc = resource,params = 参数

字体名可到 Windows 的 C:\Windows\Fonts 目录里找(如宋体等中文字体)。 - 调整画布大小(约 20:30):y 轴作者名文字超出图表左侧被截断,回忆 Matplotlib 图表结构——背景区域由 figure 决定,于是查文档在初始化时传 figsize=(宽, 高),单位是英寸(inch),把图拉宽即可(不用手动拖窗口)。 - 还用到了反转 y 轴顺序的接口,让点赞数最高的人排在最上面。

实例二:关键词提取与词云(约 25:00 - 64:45)

任务设计(约 25:20 - 27:00)

  • 把每篇回答当作一篇文章,用自然语言处理工具分词,并用算法提取主题词(关键词)排序;汇总所有回答的关键词权重,取前 100 名画词云——权重越高词在词云中面积越大。

jieba 分词库(约 27:30 - 29:00)

  • jieba(结巴):GitHub 上最流行的 Python 中文分词组件,"做最好的 Python 中文分词组件"。
  • 基本分词:一句话(如"我来到北京清华大学")可按不同模式切成词。
  • jieba 自带基于 TF-IDF 的关键词提取功能(jieba.analyse 接口)。

TF-IDF 算法原理(约 29:00 - 40:15,老师声明非自己专业领域,讲解力求通俗)

  • TF(Term Frequency,词频):最朴素的方法——一个词在当前文章出现次数越多,越可能是主题词。计算:词在本文出现次数 ÷ 文章总词数(如 100/1000 = 0.1)。
  • TF 的缺陷:有些词在所有文章里都高频出现(如三篇都是讲 Python 的文章里,"Python"一词每篇都很多),但它不能区分各篇文章的真正侧重(可视化/爬虫/游戏)。
  • IDF(Inverse Document Frequency,逆向文档频率):衡量词在整个语料库(全部 n 篇文档)中的普遍程度——

IDF = log( 文档总数 / (包含该词的文档数 + 1) )

  • 分母只数"在多少篇文档里出现过",单篇内出现 1 万次也只算 1;
  • 分母 +1 是为了避免除零(某词一篇都没出现时);
  • 取 log 是为了避免增长过快(有专门文章论证,课上不展开);
  • 一个词在越多文档中出现,IDF 越低,说明它是大家共有的词,对单篇文章主题的代表性越弱。
  • TF-IDF = TF × IDF:既看词在本文的频率,又看它在全语料库的稀缺程度,乘积即该词对单篇文章的重要性。

关键词提取的代码流程(约 40:20 - 55:50)

处理流程设计(画板讲解):每篇回答 → TF-IDF 提取出"关键词: 权重"字典(取前 10 个)→ 572 个字典拼成总表 → 按关键词分类汇总权重 → 降序排序取前 100 → 作为词云输入。

  • getAnswers() 函数:pd.read_csv 读入 → 取 content 列 → list() 转成 Python 列表(df['content'] 取出来是 Series,转列表是个人习惯,不转也行)。
  • 停用词(stop words,约 44:50):要人工忽略的词——语气词(啊、呀)、标点、与主题无关的词。本例想把高频"软件"提取出来,所以把"windows、输入法、软件、卸载、exe、图形、电脑、安装"等词写进一个 txt(一行一个词),用 jieba.analyse.set_stop_words('路径') 设置。演示用的停用词表并不完善,仅作示例。
  • 关键词提取(第 17 行,jieba 文档标准用法):
jieba.analyse.extract_tags(文本, topK=10, withWeight=True)
  • 参数 1:要提取的文章字符串;参数 2 topK:返回排名前几个关键词(这里 10);参数 3 withWeight=True:连同权重一起返回(后面要跨文章累加权重,所以必须带权重)。
  • 拼总表:先建只有列名(keyword、weight)的空 DataFrame,每个回答的关键词表用 df.append() 拼接(与列表 append 类似),得到 4000 多行的大表(DataFrame 打印时会自动省略中间行)。
  • 复用案例一套路:groupby('keyword').sum() 按关键词汇总权重 → sort_values 降序 → 取前 100。
  • 中间结果观察:360 权重特别高(很多回答提到)、surface(话题是软件但有人推荐硬件)、护眼、命令提示符等——不太直观,需要词云可视化。

wordcloud 词云库(约 55:50 - 64:45)

  • GitHub 上的 wordcloud 库,文档的 API reference 主要就四个类,本例只用 WordCloud 类;支持蒙版(如星战头盔形状)等酷炫效果。
  • 安装:pipenv install wordcloud;导入 from wordcloud import WordCloud, STOPWORDS(库内置英文停用词)。
  • 初始化(5 个参数):
wc = WordCloud(
    font_path='仿宋.ttf',      # ① 字体:必须是中文字体,否则中文显示成方块
    width=1920, height=1080,   # ②③ 词云宽高
    background_color='white',  # ④ 背景色
    stopwords=STOPWORDS        # ⑤ 停用词(用其自带的,这句可省略,也可自行添加)
)
wc.generate_from_frequencies(字典)   # 从词频生成:参数是 {关键词: 浮点权重} 字典
  • DataFrame 转字典:top100['weight'].to_dict()——取 weight 这个 Series 再 to_dict(),因为词云输入要求是字典。
  • 生成的 wordcloud 对象本质类似图片矩阵,可直接作为 Matplotlib imshow() 的输入:建画布 → plt.imshow(wc) → 关掉坐标轴显示、不留空白 → plt.show()。
  • 结果:词云被 360"占领",还有 Adobe、Fiddler(分析 HTTP 协议的代理工具)、安卓文件共享应用、iTunes、压缩工具等;也有不相关的词(命令提示符、国际版、手机、8.1 等),说明停用词表和处理逻辑还可进一步优化,但大致逻辑已成功。
  • 老师提醒:这个思路可迁移到任何爬取的数据(电影、音乐等)。

示例与演示

  • 作业/案例一:知乎"Windows 应用软件"话题回答数据 → 按作者分类汇总点赞数 → 降序取前十 → 横向柱状图。要求复现"读数据 → 取两列 → groupby 求和 → 排序 → 画图"全链路,并处理中文字体与画布大小。
  • 作业/案例二:同一数据 → jieba TF-IDF 提取每篇回答前 10 关键词(带权重)→ append 拼总表 → groupby 汇总 → 降序取前 100 → wordcloud 画词云。
  • 老师全程演示"打印驱动编程":每写一步先 print 验证(读完打印 df、取列后打印、分组求和后打印、提取关键词后先注释掉拼接逻辑单独打印关键词效果)。
  • 课堂互动:讲完 TF-IDF 让学生打 1 确认理解;课末 3 点整休息 10 分钟。

重点与难点

  • **分类汇总(groupby + sum)**是本章核心操作:groupby 只分组,必须再接 sum 等聚合方法。
  • loc[:, ['col1', 'col2']] 取列、sort_values(ascending=False) 降序、切片取前 N 的组合套路在两个案例中反复使用。
  • 中文乱码:Matplotlib 和 wordcloud 都必须显式指定中文字体(rcParams['font.sans-serif'] / font_path),否则中文变方块。
  • figsize 单位是英寸;y 轴标签被截断时调大 figure 宽度。
  • 数据质量意识:未登录爬取的"知乎用户"是多人的集合,应排除;TF-IDF 结果中混有不相关词,停用词表需要迭代完善。
  • TF-IDF 理解要点:TF 看本文频率,IDF 看全语料稀缺度(分母 +1 防除零,取 log 防增长过快),二者相乘。
  • extract_tags(文本, topK, withWeight=True):要跨文章累加权重就必须带权重返回。
  • 词云输入是 {词: 权重} 字典;DataFrame 用 df['weight'].to_dict() 转换。

关联内容

  • 综合运用前面所有章节:爬虫(第 14 章,数据来源)、csv/文件读取(15.1)、Pandas 数据处理(15.2 的 loc/groupby 前奏、排序、NaN)、Matplotlib 可视化(15.3 的 figure 结构、show)。
  • 本课即 15.3 末尾预告的**作业**:爬虫数据 → Pandas 处理 → Matplotlib 画图;老师提前把作业发布在课件网站和群里。
  • 引入新第三方库:jieba(中文分词 + TF-IDF)、wordcloud(词云),延续"查 GitHub/官方文档 → 模仿示例"的学习方法。
  • TF-IDF 属自然语言处理/文本挖掘入门内容,老师声明非专业方向,感兴趣可自查通俗资料深入。