Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第15章 报表程序 - 让数据说话

引言:从数字到图表

想象一下,如果你是一名老师,手里有一份学生的考试成绩单,上面只有密密麻麻的数字:

小明: 语文85 数学92 英语78
小红: 语文90 数学88 英语95
小刚: 语文78 数学85 英语82
...

你能快速看出:

  • 哪个科目最难?
  • 每个学生的强项是什么?
  • 全班的平均成绩如何?

如果把这些数字画成图表,比如柱状图或折线图,答案就会一目了然!这就是数据可视化的作用——把枯燥的数字变成直观的图形,让数据“说话“。

什么是报表程序?

报表程序就是用来收集、处理和展示数据的程序。在我们的日常生活中:

  • 天气预报:用折线图显示未来一周的气温变化
  • 股票软件:用K线图显示股票价格波动
  • 运动APP:用饼图显示你今天的运动时间分配
  • 游戏排行榜:用柱状图显示玩家积分排名

这些程序都有一个共同点:把数据变成图表,让人更容易理解数据背后的信息。

为什么学习报表程序?

学习制作报表程序,你将掌握:

  1. 数据处理能力:学会整理和分析数据
  2. 可视化思维:学会用图形表达信息
  3. 实用工具:能制作出真正有用的程序

比如,你可以:

  • 制作班级成绩分析报告
  • 记录自己的零花钱使用情况
  • 统计家里的电费水费变化
  • 分析自己喜欢的游戏数据

本章学习路线

本章将教你如何使用pyecharts库制作各种图表,同时融入数学统计知识:

第1步: 安装和配置pyecharts库
   ↓
第2步: 复习数学统计知识(平均数、中位数、众数)
   ↓
第3步: 柱状图 - 比较不同类别的数据
   ↓
第4步: 折线图 - 显示数据的变化趋势
   ↓
第5步: 饼图 - 显示各部分占整体的比例
   ↓
第6步: 综合项目 - 制作完整的数据报表

👨‍🏫 给家长的小贴士

  • 数据可视化是现代信息时代的重要技能
  • 图表能培养孩子的抽象思维能力
  • 本章重点融入小学数学统计知识:平均数、中位数、众数、数据分组
  • 建议选择孩子感兴趣的数据(如游戏数据、运动数据)作为练习素材
  • 鼓励孩子用图表解决实际问题(如班级统计、家庭记账)
  • 数学知识点提醒:
    • 平均数 = 总数 ÷ 个数
    • 中位数:数据从大到小排列,中间位置的数
    • 众数:出现次数最多的数
    • 方差:数据波动大小的衡量(本章会简单介绍)

15.1 认识pyecharts库

15.1.1 什么是pyecharts?

pyecharts是一个专门用于生成图表的Python库。它的名字可以拆解为:

  • py: Python的缩写
  • echarts: 百度开源的一个强大图表工具
  • s: 表示这是echarts的Python版本

为什么要使用pyecharts?

  1. 功能强大: 支持几十种图表类型
  2. 美观漂亮: 生成的图表配色和样式都很专业
  3. 易于使用: 只需要几行代码就能生成图表
  4. 交互式: 生成的图表支持鼠标悬停、点击缩放等操作

15.1.2 安装pyecharts

在开始使用pyecharts之前,需要先安装它。还记得我们在第13章学过的pip工具吗?

步骤1: 打开命令行窗口

Windows系统:

  1. 按Win+R键
  2. 输入cmd
  3. 按回车键

Mac系统:

  1. 按Command+空格键
  2. 输入“终端“
  3. 按回车键

步骤2: 安装pyecharts

在命令行窗口中输入以下命令:

pip install pyecharts

你会看到类似这样的输出:

Collecting pyecharts
  Downloading pyecharts-2.0.4-py3-none-any.whl (...)
Installing collected packages: pyecharts
Successfully installed pyecharts-2.0.4

步骤3: 验证安装

安装完成后,在Python中输入以下代码测试:

from pyecharts.charts import Bar
print("pyecharts安装成功!")

如果输出“pyecharts安装成功!“说明安装成功了!

步骤4: (可选)安装图片快照功能

如果你想直接把图表保存为图片格式,需要安装额外的插件:

pip install pyecharts_snapshot

这个功能可以把HTML格式的图表转换为PNG或JPG图片。

给家长的小贴士

  • pip安装失败: 可能是因为网络问题,可以尝试使用国内镜像源:pip install pyecharts -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 权限问题: 如果提示权限不足,在Windows上以管理员身份运行命令行,Mac上使用sudo
  • 版本问题: pyecharts有v1和v2两个版本,本书使用v2版本
  • 离线安装: 如果网络不好,可以下载whl文件后本地安装

常见问题解答

Q: 为什么要安装这么大的库? A: pyecharts包含了大量的图表模板和样式文件,所以比较大。但这些文件让我们能做出更专业的图表。

Q: 安装失败怎么办? A: 1) 检查网络连接 2) 尝试升级pip:python -m pip install --upgrade pip 3) 使用国内镜像源

Q: 每次使用都要重新安装吗? A: 不需要!安装一次后,以后在任何Python程序中都可以使用。

15.1.3 pyecharts的基本使用流程

使用pyecharts生成图表一般分为5个步骤:

# 步骤1: 导入需要的图表类
from pyecharts.charts import Bar

# 步骤2: 创建图表对象
bar = Bar()

# 步骤3: 添加数据
bar.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
bar.add_yaxis("商家A", [5, 20, 36, 10, 10, 100])

# 步骤4: 设置全局选项(可选)
bar.set_global_opts(title_opts={"text": "我的第一个图表"})

# 步骤5: 渲染生成HTML文件
bar.render("my_first_chart.html")

代码解析:

  1. 导入: 从pyecharts.charts导入你需要的图表类(如Bar、Line、Pie)
  2. 创建: 创建一个图表对象
  3. 数据: 用add_xaxis()添加x轴数据,用add_yaxis()添加y轴数据
  4. 选项: 设置标题、图例、工具箱等配置
  5. 渲染: 生成一个HTML文件,用浏览器打开就能看到图表

运行结果: 程序运行后,会在当前目录下生成my_first_chart.html文件。双击这个文件,浏览器会打开它,你就能看到一个漂亮的柱状图了!

给家长的小贴士

  • HTML文件: 生成的图表是网页格式(HTML),不需要额外安装软件就能打开
  • 代码结构: 强调“导入-创建-添加数据-设置选项-渲染“这5步固定流程
  • 逐步演示: 建议先让孩子看完整的运行效果,激发学习兴趣
  • 文件位置: 提醒孩子注意HTML文件的保存位置,方便查找

实践练习1:修改数据

任务: 将上面的代码复制下来,修改数据:

  • x轴改成你喜欢的6种水果
  • y轴改成每种水果的价格(元)
  • 标题改成“水果价格表“

提示:

bar.add_xaxis(["苹果", "香蕉", "橙子", "草莓", "葡萄", "西瓜"])
bar.add_yaxis("价格", [8, 3, 6, 15, 12, 5])

答案:

点击查看完整代码
from pyecharts.charts import Bar

# 创建图表对象
bar = Bar()

# 添加数据
bar.add_xaxis(["苹果", "香蕉", "橙子", "草莓", "葡萄", "西瓜"])
bar.add_yaxis("价格(元)", [8, 3, 6, 15, 12, 5])

# 设置标题
bar.set_global_opts(title_opts={"text": "水果价格表"})

# 生成图表
bar.render("fruit_price.html")

运行后打开fruit_price.html,你就能看到水果价格的柱状图了!


15.2 数学统计知识复习 📊

在开始制作图表之前,让我们先复习一些数学统计知识。这些知识会在制作图表时经常用到!

15.2.1 平均数(Average)

什么是平均数?

平均数是一组数据的“代表值“,它能反映这组数据的整体水平

🍎 生活中的例子: 假设你有5个苹果,分别重: 150克、160克、140克、155克、145克。

计算平均数的步骤:

# 步骤1: 把所有数据加起来
total = 150 + 160 + 140 + 155 + 145
print("总重量:", total)  # 输出: 750克

# 步骤2: 除以数据的个数
average = total / 5
print("平均重量:", average)  # 输出: 150克

用Python计算平均数:

# 一组数据
scores = [85, 90, 78, 92, 88]

# 方法1: 使用sum()和len()
average = sum(scores) / len(scores)
print(f"平均分: {average}")

# 方法2: 用循环计算
total = 0
for score in scores:
    total += score
average = total / len(scores)
print(f"平均分: {average}")

平均数的数学意义:

  • 如果每个人的成绩都等于平均分,那么总分不会变
  • 平均数是“公平“的体现——每个人贡献相同

👨‍🏫 给家长的小贴士

  • 平均数 vs 总数: 问孩子“为什么有了总数还要算平均数?“(因为人数不同时,总数不能直接比较)
  • 生活中的平均数: 平均气温、平均身高、平均速度、平均价格
  • 计算技巧: 先估算,再精确计算。比如[85, 90, 78, 92, 88],可以估算“大约85左右“
  • 错误认知: 平均数不一定是数据中的某个值(比如[1, 2, 10],平均数是4.33,不在原数据中)

15.2.2 中位数(Median)

什么是中位数?

中位数是把数据按大小排列后,位于中间位置的那个数。

🏃 生活中的例子: 跑步比赛,5个人的成绩是:

  • 3分20秒、3分15秒、3分25秒、3分18秒、3分22秒

找中位数的步骤:

# 步骤1: 把数据从小到大排列
times = [3*60+15, 3*60+18, 3*60+20, 3*60+22, 3*60+25]  # 转换为秒
print("排序前:", times)

# 使用Python排序
times_sorted = sorted(times)
print("排序后:", times_sorted)  # [195, 198, 200, 202, 205]

# 步骤2: 找中间位置的数据(第3个)
median_index = len(times_sorted) // 2  # 5//2 = 2(索引从0开始)
median = times_sorted[median_index]
print(f"中位数: {median}秒,即{median//60}分{median%60}秒")

中位数的特点:

  • 数据个数是奇数时,中位数就是中间的那个数
  • 数据个数是偶数时,中位数是中间两个数的平均数

偶数个数据的例子:

# 6个数据
scores = [85, 90, 78, 92, 88, 95]

# 排序
scores_sorted = sorted(scores)  # [78, 85, 88, 90, 92, 95]

# 中间两个数: 第3个(88)和第4个(90)
middle1 = scores_sorted[2]   # 第3个,索引为2
middle2 = scores_sorted[3]   # 第4个,索引为3

median = (middle1 + middle2) / 2
print(f"中位数: {median}")  # 输出: 89.0

中位数的数学意义:

  • 中位数不受极端值(太大或太小的数)的影响
  • 比如工资统计,如果有一个人工资特别高,平均数会失真,但中位数能反映真实情况

👨‍🏫 给家长的小贴士

  • 平均数 vs 中位数: 举例说明差异
    • 班级成绩: [60, 85, 88, 90, 92],平均数=83,中位数=88(接近)
    • 班级成绩: [10, 85, 88, 90, 92],平均数=73,中位数=88(差异大)
  • 什么时候用中位数: 当有极端值(异常大或异常小的数据)时
  • 排序技能: 教孩子手动排序的方法(冒泡排序的简化版)
  • 找位置: 奇数个数据的位置 = (总数+1)÷2,偶数个数据取中间两个的平均

15.2.3 众数(Mode)

什么是众数?

众数是一组数据中出现次数最多的数。

🎨 生活中的例子: 班级同学最喜欢的颜色统计:

  • 红色:5人、蓝色:8人、绿色:3人、黄色:8人、紫色:2人
# 数据
colors = ["红", "蓝", "绿", "黄", "紫"]
counts = [5, 8, 3, 8, 2]

# 找最大值
max_count = max(counts)
print(f"最多人选的人数: {max_count}")

# 找最大值的位置
max_index = counts.index(max_count)
mode_color = colors[max_index]
print(f"众数(最受欢迎的颜色): {mode_color}")

多个众数的情况:

# 数据: [1, 2, 2, 3, 3, 4]
# 2出现2次,3也出现2次
# 这组数据有"双众数": 2和3

# 统计每个数出现的次数
from collections import Counter

data = [1, 2, 2, 3, 3, 4]
count_result = Counter(data)
print("统计结果:", count_result)  # Counter({2: 2, 3: 2, 1: 1, 4: 1})

# 找出现最多的次数
max_count = max(count_result.values())

# 找所有众数
modes = [num for num, count in count_result.items() if count == max_count]
print(f"众数: {modes}")  # 输出: [2, 3]

众数的特点:

  • 一组数据可能没有众数(所有数都只出现1次)
  • 一组数据可能有多个众数
  • 众数一定是数据中的某个值(这一点和平均数不同!)

👨‍🏫 给家长的小贴士

  • 众数 vs 平均数: 众数关注“最多“,平均数关注“整体“
  • 投票选举: 众数就像民主投票,得票最多的当选
  • 实际应用:
    • 商店进货哪种商品(卖得最好的)
    • 鞋厂生产哪种尺码(穿的人最多的)
  • 编程思维: 用字典统计频次是常见的数据处理方法

15.2.4 数据分组(区间统计)

什么是数据分组?

当数据很多时,我们不会逐个统计,而是把数据分成几个区间(范围),统计每个区间有多少个数据。

📊 生活中的例子:

统计班级50个学生的考试成绩:

  • 100分: 3人
  • 90-99分: 12人
  • 80-89分: 20人
  • 70-79分: 10人
  • 60-69分: 4人
  • 60分以下: 1人

用Python实现数据分组:

# 原始成绩数据
scores = [95, 87, 92, 78, 85, 90, 88, 92, 85, 76,
          82, 89, 91, 85, 88, 90, 87, 85, 92, 88]

# 定义分数段
ranges = ["优秀(90-100)", "良好(80-89)", "及格(60-79)", "不及格(0-59)"]
counts = [0, 0, 0, 0]

# 统计每个分数段的人数
for score in scores:
    if score >= 90:
        counts[0] += 1
    elif score >= 80:
        counts[1] += 1
    elif score >= 60:
        counts[2] += 1
    else:
        counts[3] += 1

print("分数段分布:")
for i in range(len(ranges)):
    print(f"{ranges[i]}: {counts[i]}人")

数据分组的数学意义:

  • 简化数据,让数据更容易理解
  • 保留数据的整体趋势,同时忽略细节
  • 方便制作统计图表(直方图、饼图)

分组的技巧:

  1. 等距分组: 每个区间的长度相同(如0-10, 10-20, 20-30)
  2. 有意义分组: 根据实际意义划分(如成绩的优、良、及格)
  3. 边界明确: 明确区间的起点和终点(包括端点吗?)

👨‍🏫 给家长的小贴士

  • 为什么分组: 问孩子“50个人的成绩,逐个柱状图会很拥挤,怎么办?“(引出分组)
  • 选择区间: 举例说明区间太大或太小的问题
    • 太大: [0-100]只有一个区间,没意义
    • 太小: [0-1, 1-2, 2-3…]太细碎
    • 合适: [0-59, 60-69, 70-79, 80-89, 90-100]
  • 包含边界: 90分属于哪个区间?需要约定(通常“左闭右开“[90,100)或“左开右闭“(89,100])
  • 图表对应: 分组数据适合做饼图,显示各部分占比

15.2.5 综合练习:数据分析

现在让我们用刚才学到的统计知识,分析一组真实数据!

📚 案例分析:班级阅读情况统计

# 班级同学这学期阅读的书籍数量
books_read = [5, 8, 12, 6, 7, 10, 9, 8, 15, 6,
              7, 8, 9, 11, 7, 8, 10, 12, 8, 9]

# 1. 计算平均数
average = sum(books_read) / len(books_read)
print(f"平均每人读{average:.1f}本书")

# 2. 找中位数
sorted_books = sorted(books_read)
n = len(sorted_books)
if n % 2 == 1:  # 奇数个
    median = sorted_books[n // 2]
else:  # 偶数个
    median = (sorted_books[n // 2 - 1] + sorted_books[n // 2]) / 2
print(f"中位数: {median}本")

# 3. 找众数
from collections import Counter
count_result = Counter(books_read)
max_count = max(count_result.values())
modes = [num for num, count in count_result.items() if count == max_count]
print(f"众数: {modes}本")

# 4. 数据分组
ranges = ["0-5本", "6-10本", "11-15本", "16本以上"]
counts = [0, 0, 0, 0]
for books in books_read:
    if books <= 5:
        counts[0] += 1
    elif books <= 10:
        counts[1] += 1
    elif books <= 15:
        counts[2] += 1
    else:
        counts[3] += 1

print("\n阅读量分组统计:")
for i in range(len(ranges)):
    percentage = counts[i] / len(books_read) * 100
    print(f"{ranges[i]}: {counts[i]}人,占{percentage:.1f}%")

运行结果:

平均每人读8.7本书
中位数: 8.0本
众数: [8]本

阅读量分组统计:
0-5本: 1人,占5.0%
6-10本: 15人,占75.0%
11-15本: 4人,占20.0%
16本以上: 0人,占0.0%

数据分析结论:

  • 大部分同学(75%)阅读量在6-10本之间
  • 平均数(8.7本)和中位数(8本)接近,说明数据分布比较均匀
  • 众数是8本,说明阅读8本的同学最多
  • 全班没有一个人阅读超过15本,但也没有一个人阅读少于6本(除了1人)

👨‍🏫 给家长的小贴士

  • 数据思维: 教孩子从数据中“读故事“,而不是只看数字
  • 多角度分析: 平均数、中位数、众数各有用处,综合分析更全面
  • 批判性思维: 问孩子“如果你是老师,看到这个数据会怎么做?“(比如:组织读书分享会)
  • 现实应用: 鼓励孩子用这套方法分析自己的数据(游戏时长、学习时间等)
  • 编程价值: 强调Python让数据分析变得简单高效,手算20个数据要很久,Python只需要几秒

🎯 实践练习2:你自己的数据分析

任务: 收集一组你感兴趣的数据,并用Python分析:

数据主题建议:

  1. 游戏数据: 最近10次游戏的得分/等级
  2. 运动数据: 最近2周每天的运动时长
  3. 学习数据: 最近10次作业的分数
  4. 创意数据: 其他你感兴趣的数据

要求:

  • 至少10个数据点
  • 计算平均数、中位数、众数
  • 进行数据分组(至少3个区间)
  • 写出分析结论(至少3条)

答案示例:

点击查看参考答案
# 示例:游戏得分分析
scores = [85, 92, 78, 88, 95, 82, 90, 87, 91, 89]

# 平均数
avg = sum(scores) / len(scores)
print(f"平均分: {avg:.1f}")

# 中位数
sorted_scores = sorted(scores)
median = (sorted_scores[4] + sorted_scores[5]) / 2
print(f"中位数: {median}")

# 众数
from collections import Counter
count_result = Counter(scores)
max_count = max(count_result.values())
modes = [s for s, c in count_result.items() if c == max_count]
print(f"众数: {modes}")

# 数据分组
ranges = ["优秀(90-100)", "良好(80-89)", "及格(60-79)", "不及格(0-59)"]
counts = [0, 0, 0, 0]
for score in scores:
    if score >= 90:
        counts[0] += 1
    elif score >= 80:
        counts[1] += 1
    elif score >= 60:
        counts[2] += 1
    else:
        counts[3] += 1

print("\n分数段分布:")
for i in range(len(ranges)):
    print(f"{ranges[i]}: {counts[i]}人")

15.3 柱状图 - 比较大小的高手

15.3.1 柱状图的应用场景

**柱状图(Bar Chart)**是最常见的图表类型之一,它用柱子的高度来表示数据的大小。

柱状图适合用来:

  • 比较不同类别: 比较不同产品的销量
  • 排名: 显示班级成绩排名
  • 统计: 统计每个月的零花钱支出

生活中的柱状图例子:

  • 奥运会奖牌榜
  • 游戏英雄战斗力对比
  • 各城市人口数量对比

15.3.2 创建一个简单的柱状图

让我们从最简单的例子开始——制作一个班级成绩的柱状图:

from pyecharts.charts import Bar

# 创建柱状图
bar = Bar()

# 添加x轴数据(学生姓名)
bar.add_xaxis(["小明", "小红", "小刚", "小丽", "小华"])

# 添加y轴数据(语文成绩)
bar.add_yaxis("语文成绩", [85, 90, 78, 92, 88])

# 设置标题
bar.set_global_opts(title_opts={"text": "班级语文成绩"})

# 生成HTML文件
bar.render("class_scores.html")

运行结果: 程序会生成class_scores.html文件,用浏览器打开后,你会看到5个不同高度的柱子,每个柱子代表一个学生的语文成绩。

15.3.3 添加多个系列的数据

有时候我们需要对比多组数据。比如,想同时显示每个学生的语文、数学、英语成绩:

from pyecharts.charts import Bar

bar = Bar()

# 添加x轴(学生姓名)
bar.add_xaxis(["小明", "小红", "小刚", "小丽", "小华"])

# 添加多组数据
bar.add_yaxis("语文", [85, 90, 78, 92, 88])
bar.add_yaxis("数学", [92, 88, 85, 95, 90])
bar.add_yaxis("英语", [78, 95, 82, 88, 91])

# 设置标题
bar.set_global_opts(title_opts={"text": "班级成绩表"})

# 生成图表
bar.render("class_scores_all.html")

图表解读:

  • 每个学生会有3根柱子,分别代表语文、数学、英语成绩
  • 不同颜色的柱子代表不同的科目
  • 图表右上角会显示图例(语文、数学、英语),点击可以隐藏/显示对应的数据

给家长的小贴士

  • 颜色区分: 帮助孩子理解不同颜色代表不同数据系列
  • 图例功能: 演示点击图例可以隐藏/显示数据,这是pyecharts的交互功能
  • 数据对应: 确保x轴和y轴的数据数量一致,否则会报错
  • 中文字符: pyecharts完全支持中文,不会出现乱码问题

实践练习2:最喜欢的运动统计

任务: 调查班级同学最喜欢的运动,制作柱状图:

  • x轴: 篮球、足球、羽毛球、乒乓球、跑步、游泳
  • y轴: 喜欢该项运动的人数(假设为: 15, 12, 8, 10, 6, 9)
  • 标题: “班级运动喜好调查”

要求:

  1. 添加y轴名称:“人数”
  2. 添加数据标签显示每个柱子上的具体数值

答案:

点击查看完整代码
from pyecharts.charts import Bar
from pyecharts import options as opts

bar = Bar()

# 添加数据
bar.add_xaxis(["篮球", "足球", "羽毛球", "乒乓球", "跑步", "游泳"])
bar.add_yaxis(
    series_name="人数",
    yaxis_data=[15, 12, 8, 10, 6, 9],
    label_opts=opts.LabelOpts(is_show=True)  # 显示数据标签
)

# 设置全局选项
bar.set_global_opts(
    title_opts={"text": "班级运动喜好调查"},
    yaxis_opts=opts.AxisOpts(name="人数"),
    xaxis_opts=opts.AxisOpts(name="运动项目")
)

# 生成图表
bar.render("sports_survey.html")

运行后,每个柱子上会显示具体人数,方便读取数据!

15.3.4 柱状图的高级设置

1. 水平柱状图

默认的柱状图是垂直的,柱子从下往上。有时我们需要水平的柱状图,柱子从左往右:

from pyecharts.charts import Bar
from pyecharts import options as opts

bar = Bar()

# 添加数据(反转x和y轴的添加顺序)
bar.add_xaxis(["篮球", "足球", "羽毛球", "乒乓球", "跑步", "游泳"])
bar.add_yaxis("人数", [15, 12, 8, 10, 6, 9])

# 设置全局选项
bar.set_global_opts(
    title_opts={"text": "班级运动喜好调查"},
    yaxis_opts=opts.AxisOpts(name="人数"),
    xaxis_opts=opts.AxisOpts(name="运动项目")
)

# 反转x轴和y轴
bar.reversal_axis()

# 生成图表
bar.render("horizontal_bar.html")

使用场景: 水平柱状图适合类别名称很长的情况(如“数学竞赛成绩“、“英语演讲比赛“等),避免文字重叠。

2. 堆叠柱状图

堆叠柱状图可以让多组数据叠加显示:

from pyecharts.charts import Bar
from pyecharts import options as opts
from pyecharts.globals import ThemeType

# 使用主题
bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))

bar.add_xaxis(["第一季度", "第二季度", "第三季度", "第四季度"])
bar.add_yaxis("电子产品", [10, 20, 30, 40], stack="stack1")
bar.add_yaxis("服装", [15, 25, 20, 35], stack="stack1")
bar.add_yaxis("食品", [20, 15, 25, 30], stack="stack1")

bar.set_global_opts(
    title_opts={"text": "季度销售额"},
    yaxis_opts=opts.AxisOpts(name="销售额(万元)"),
    xaxis_opts=opts.AxisOpts(name="季度"),
    toolbox_opts=opts.ToolboxOpts(is_show=True)  # 显示工具栏
)

bar.render("stacked_bar.html")

使用场景: 堆叠柱状图适合显示部分与整体的关系,比如每天不同类别商品的销售总额。

给家长的小贴士

  • 主题样式: pyecharts提供了多个主题(LIGHT, DARK, ROMA等),可以尝试不同风格
  • 工具栏: toolbox_opts会显示下载图片、数据视图等功能,很实用
  • 堆叠概念: 用积木叠高高来类比堆叠柱状图,孩子更容易理解
  • 代码复用: 鼓励孩子把常用配置保存起来,下次直接使用

15.3.5 柱状图的常见问题

问题1: 中文显示乱码

虽然pyecharts默认支持中文,但如果你的Python文件编码不是UTF-8,可能会出现乱码。

解决方法: 在Python文件的第一行添加:

# -*- coding: utf-8 -*-

问题2: 柱子太多显示不下

当x轴的类别太多时,柱子会挤在一起。

解决方法:

bar.set_global_opts(
    xaxis_opts=opts.AxisOpts(
        axislabel_opts=opts.LabelOpts(rotate=45)  # 旋转标签45度
    )
)

问题3: 数值差异太大

如果一组数据是[5, 8, 10],另一组是[1000, 2000, 3000],数值小的柱子几乎看不见。

解决方法: 使用双y轴(在高级应用中会学习)或调整数据比例。

实践练习3:比较自己和偶像的数据

任务: 制作一个柱状图,对比你和偶像的数据(可以是游戏、运动、学习等):

  • 要求:至少3个对比项目(如:身高、体重、年龄,或游戏等级、胜率、场次)
  • 使用水平柱状图
  • 添加标题和数据标签

示例数据:

me = [165, 50, 12]  # 身高cm, 体重kg, 年龄
idol = [178, 65, 25]
items = ["身高(cm)", "体重(kg)", "年龄"]

答案:

点击查看完整代码
from pyecharts.charts import Bar
from pyecharts import options as opts

# 你的数据
me = [165, 50, 12]
idol = [178, 65, 25]
items = ["身高(cm)", "体重(kg)", "年龄"]

bar = Bar()

bar.add_xaxis(items)
bar.add_yaxis("我", me, label_opts=opts.LabelOpts(is_show=True))
bar.add_yaxis("偶像", idol, label_opts=opts.LabelOpts(is_show=True))

bar.set_global_opts(
    title_opts={"text": "我和偶像的对比"}
)

bar.reversal_axis()
bar.render("me_vs_idol.html")

15.4 折线图 - 追踪变化趋势

15.4.1 折线图的应用场景

**折线图(Line Chart)**用线段连接各个数据点,显示数据随时间或其他因素的变化趋势。

折线图适合用来:

  • 显示趋势: 比如一年的气温变化
  • 对比变化: 比较两个学生的成绩进步情况
  • 预测未来: 根据历史数据预测趋势

生活中的折线图例子:

  • 天气预报的气温曲线
  • 新冠疫情的数据曲线
  • 股票价格的K线图

15.4.2 创建一个简单的折线图

让我们制作一个显示一周气温变化的折线图:

from pyecharts.charts import Line

# 创建折线图
line = Line()

# 添加x轴数据(星期)
line.add_xaxis(["周一", "周二", "周三", "周四", "周五", "周六", "周日"])

# 添加y轴数据(最高气温)
line.add_yaxis("最高气温(°C)", [22, 24, 26, 25, 23, 28, 30])

# 设置标题
line.set_global_opts(title_opts={"text": "一周气温变化"})

# 生成图表
line.render("temperature_line.html")

图表解读:

  • x轴表示星期
  • y轴表示温度
  • 折线显示温度的变化趋势
  • 可以看出哪天最热,哪天最凉快

15.4.3 添加多个数据系列

折线图特别适合对比多个数据系列的变化趋势:

from pyecharts.charts import Line

line = Line()

# 添加x轴
line.add_xaxis(["周一", "周二", "周三", "周四", "周五", "周六", "周日"])

# 添加多组数据
line.add_yaxis("最高气温(°C)", [22, 24, 26, 25, 23, 28, 30])
line.add_yaxis("最低气温(°C)", [15, 16, 18, 17, 14, 19, 20])

# 设置标题
line.set_global_opts(title_opts={"text": "一周气温变化"})

# 生成图表
line.render("temperature_double_line.html")

图表解读:

  • 两条折线分别代表最高气温和最低气温
  • 可以看出每天的温差(两条线之间的距离)
  • 可以看出气温的总体变化趋势

给家长的小贴士

  • 趋势解读: 教孩子如何从折线图中读取信息(上升、下降、波动)
  • 数据对比: 多条折线对比时,引导孩子找出规律(如:A一直比B高,A和B呈相反变化)
  • 实际应用: 鼓励孩子记录自己的数据(如每天的学习时间),用折线图分析
  • 数据收集: 这个过程还能培养孩子的数据收集习惯

实践练习4:我的成绩进步曲线

任务: 制作一个折线图,显示你最近5次考试的成绩变化:

  • x轴: 第1次、第2次、第3次、第4次、第5次
  • y轴: 语文和数学的成绩
  • 添加数据标记点

示例数据:

chinese = [75, 78, 82, 85, 88]
math = [80, 79, 83, 87, 90]
exams = ["第1次", "第2次", "第3次", "第4次", "第5次"]

答案:

点击查看完整代码
from pyecharts.charts import Line
from pyecharts import options as opts

# 成绩数据
chinese = [75, 78, 82, 85, 88]
math = [80, 79, 83, 87, 90]
exams = ["第1次", "第2次", "第3次", "第4次", "第5次"]

line = Line()

line.add_xaxis(exams)
line.add_yaxis(
    "语文",
    chinese,
    markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")]),
    markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(type_="average")])
)
line.add_yaxis("数学", math)

line.set_global_opts(
    title_opts={"text": "我的成绩进步曲线"},
    yaxis_opts=opts.AxisOpts(name="分数"),
    xaxis_opts=opts.AxisOpts(name="考试次数")
)

line.render("my_scores.html")

运行后,你会看到两条折线,语文的最高分会自动标记,平均分也会显示!

15.4.4 平滑曲线和面积图

1. 平滑曲线

默认的折线图是直线连接各个点。设置is_smooth=True可以让线条变得平滑:

from pyecharts.charts import Line

line = Line()

line.add_xaxis(["1月", "2月", "3月", "4月", "5月", "6月"])
line.add_yaxis("销售额(万元)", [10, 15, 13, 18, 20, 25], is_smooth=True)

line.set_global_opts(title_opts={"text": "上半年销售额"})

line.render("smooth_line.html")

效果: 折线变成了平滑的曲线,看起来更美观,适合表示连续变化的数据(如气温、速度等)。

2. 面积图

面积图是在折线图下方填充颜色,强调数据的“量“:

from pyecharts.charts import Line
from pyecharts import options as opts

line = Line()

line.add_xaxis(["周一", "周二", "周三", "周四", "周五", "周六", "周日"])
line.add_yaxis(
    "学习时间(小时)",
    [2, 2.5, 3, 2, 3.5, 4, 3],
    areastyle_opts=opts.AreaStyleOpts(opacity=0.5)  # 填充区域,透明度0.5
)

line.set_global_opts(title_opts={"text": "一周学习时间统计"})

line.render("area_line.html")

使用场景: 面积图适合强调累积量或总量,如每天的学习时间、每月的零花钱支出。

给家长的小贴士

  • 平滑 vs 直线: 平滑曲线看起来更美观,但不适合强调精确的数据点
  • 面积图: 适合用“积木堆叠“或“装水“的类比解释
  • 透明度: opacity范围是0到1,0表示完全透明,1表示不透明
  • 交互功能: 鼠标悬停在图表上时,会显示详细的数据提示框

15.4.5 折线图的标记功能

pyecharts可以在折线图上自动标记特殊点:

from pyecharts.charts import Line
from pyecharts import options as opts

line = Line()

line.add_xaxis(["1月", "2月", "3月", "4月", "5月", "6月"])
line.add_yaxis(
    "销售额(万元)",
    [10, 15, 13, 18, 20, 25],
    # 标记点:最大值、最小值
    markpoint_opts=opts.MarkPointOpts(
        data=[
            opts.MarkPointItem(type_="max", name="最大值"),
            opts.MarkPointItem(type_="min", name="最小值")
        ]
    ),
    # 标记线:平均值
    markline_opts=opts.MarkLineOpts(
        data=[
            opts.MarkLineItem(type_="average", name="平均值")
        ]
    )
)

line.set_global_opts(title_opts={"text": "上半年销售额"})

line.render("marked_line.html")

标记说明:

  • 标记点: 用圆点标记特殊位置(最大值、最小值、自定义点)
  • 标记线: 用直线标记特殊位置(平均值、自定义线)

实践练习5:游戏等级提升记录

任务: 假设你在一周内玩游戏,每天记录等级提升:

  • x轴: 周一到周日
  • y轴: 等级(假设起始等级1,每天提升不同)
  • 要求:标记最大提升的那一天,显示平均等级

示例数据:

levels = [1, 3, 5, 8, 10, 15, 18]
gains = [0, 2, 2, 3, 2, 5, 3]  # 每天提升的等级

答案:

点击查看完整代码
from pyecharts.charts import Line
from pyecharts import options as opts

levels = [1, 3, 5, 8, 10, 15, 18]
days = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]

line = Line()

line.add_xaxis(days)
line.add_yaxis(
    "等级",
    levels,
    markpoint_opts=opts.MarkPointOpts(
        data=[
            opts.MarkPointItem(type_="max", name="最高等级"),
            opts.MarkPointItem(type_="min", name="最低等级")
]
    ),
    markline_opts=opts.MarkLineOpts(
        data=[
            opts.MarkLineItem(type_="average", name="平均等级")
        ]
    )
)

line.set_global_opts(
    title_opts={"text": "游戏等级提升记录"},
    yaxis_opts=opts.AxisOpts(name="等级"),
    xaxis_opts=opts.AxisOpts(name="日期")
)

line.render("game_levels.html")

15.5 饼图 - 显示比例关系

15.5.1 饼图的应用场景

**饼图(Pie Chart)**用圆形的扇形大小表示各部分占整体的比例。

饼图适合用来:

  • 显示占比: 班级男女生比例
  • 分配关系: 零花钱的用途分配
  • 组成结构: 家庭支出中各项费用的占比

生活中的饼图例子:

  • 预算分配图
  • 选举结果占比
  • 手机存储空间使用情况

重要: 饼图的数据加起来应该是100%(或1),表示一个整体。

15.5.2 创建一个简单的饼图

让我们制作一个显示班级运动爱好的饼图:

from pyecharts.charts import Pie

# 数据
sports = ["篮球", "足球", "羽毛球", "乒乓球", "跑步", "游泳"]
counts = [15, 12, 8, 10, 6, 9]

# 创建饼图
pie = Pie()

# 添加数据
pie.add("", list(zip(sports, counts)))

# 设置标题
pie.set_global_opts(title_opts={"text": "班级运动喜好分布"})

# 生成图表
pie.render("sports_pie.html")

代码解析:

  • list(zip(sports, counts))将两个列表合并成:[("篮球", 15), ("足球", 12), ...]
  • 饼图的add()方法的第一个参数是系列名称(可以为空字符串)

15.5.3 饼图的样式设置

1. 显示百分比和标签

默认情况下,饼图会显示类别名称。我们可以同时显示百分比:

from pyecharts.charts import Pie
from pyecharts import options as opts

sports = ["篮球", "足球", "羽毛球", "乒乓球", "跑步", "游泳"]
counts = [15, 12, 8, 10, 6, 9]

pie = Pie()

pie.add(
    "",
    list(zip(sports, counts)),
    label_opts=opts.LabelOpts(formatter="{b}: {d}%")  # {b}=名称, {d}=百分比
)

pie.set_global_opts(title_opts={"text": "班级运动喜好分布"})

pie.render("sports_pie_percent.html")

formatter参数说明:

  • {a}: 系列名称
  • {b}: 数据项名称(如“篮球“)
  • {c}: 数值(如15)
  • {d}: 百分比(如18.07%)

2. 环形饼图

环形饼图比普通饼图更美观,中间是空心的:

from pyecharts.charts import Pie
from pyecharts import options as opts

sports = ["篮球", "足球", "羽毛球", "乒乓球", "跑步", "游泳"]
counts = [15, 12, 8, 10, 6, 9]

pie = Pie()

pie.add(
    "",
    list(zip(sports, counts)),
    radius=["30%", "70%"]  # 内圆半径30%,外圆半径70%
)

pie.set_global_opts(title_opts={"text": "班级运动喜好分布"})

pie.render("donut_pie.html")

radius参数:

  • 第一个值: 内圆半径
  • 第二个值: 外圆半径
  • 两个值越接近,环形越细

给家长的小贴士

  • 百分比概念: 饼图是帮助孩子理解百分比的绝佳工具
  • 数据归一化: 如果数据加起来不是100%,pyecharts会自动计算百分比
  • 颜色识别: 教孩子如何从饼图的颜色和面积大小直观地理解比例
  • 环形 vs 实心: 环形饼图可以在中间显示总数或标题,更美观

实践练习6:我的零花钱花哪里了

任务: 制作一个饼图,显示你一个月零花钱的使用情况:

  • 类别: 零食、文具、玩具、游戏、其他
  • 数据: 自己设定一个合理的分配(如: 30%, 20%, 15%, 25%, 10%)
  • 要求:使用环形饼图,显示百分比

示例数据:

items = ["零食", "文具", "玩具", "游戏", "其他"]
money = [60, 40, 30, 50, 20]  # 单位:元

答案:

点击查看完整代码
from pyecharts.charts import Pie
from pyecharts import options as opts

items = ["零食", "文具", "玩具", "游戏", "其他"]
money = [60, 40, 30, 50, 20]

pie = Pie()

pie.add(
    "",
    list(zip(items, money)),
    radius=["35%", "65%"],  # 环形
    label_opts=opts.LabelOpts(formatter="{b}: {c}元 ({d}%)")
)

pie.set_global_opts(
    title_opts={"text": "我的零花钱使用情况"},
    legend_opts=opts.LegendOpts(orient="vertical", pos_left="left")
)

pie.render("allowance_spending.html")

运行后,你会看到一个漂亮的环形饼图,每个部分显示金额和百分比!

15.5.4 饼图的Rose图

Rose图(玫瑰图)是饼图的变体,扇形的半径不同:

from pyecharts.charts import Pie
from pyecharts import options as opts

sports = ["篮球", "足球", "羽毛球", "乒乓球", "跑步", "游泳"]
counts = [15, 12, 8, 10, 6, 9]

pie = Pie()

pie.add(
    "",
    list(zip(sports, counts)),
    radius="60%",  # 半径
    rosetype="radius"  # 设置为玫瑰图
)

pie.set_global_opts(title_opts={"text": "班级运动喜好分布(Rose图)"})

pie.render("rose_pie.html")

Rose图特点:

  • 每个扇形的半径不同,数据越大,扇形越大
  • 适合数据差异较大的情况
  • 视觉效果更丰富

给家长的小贴士

  • Rose图 vs 饼图: Rose图强调数值差异,饼图强调比例关系
  • 选择建议: 数据差异大时用Rose图,数据相近时用普通饼图
  • 交互功能: 点击某个扇形,该扇形会突出显示

15.5.5 饼图的嵌套

饼图可以嵌套,显示多层数据:

from pyecharts.charts import Pie
from pyecharts import options as opts

# 内圈数据
inner_data = [("电子产品", 60), ("服装", 30), ("食品", 50)]
# 外圈数据(细分)
outer_data = [
    ("手机", 30), ("电脑", 20), ("耳机", 10),
    ("男装", 15), ("女装", 15),
    ("零食", 25), ("饮料", 15), ("水果", 10)
]

pie = Pie()

# 添加内圈
pie.add(
    "",
    inner_data,
    radius=["0%", "35%"],  # 从中心到35%的区域
    label_opts=opts.LabelOpts(formatter="{b}: {d}%")
)

# 添加外圈
pie.add(
    "",
    outer_data,
    radius=["45%", "70%"],  # 从45%到70%的区域
    label_opts=opts.LabelOpts(formatter="{b}: {d}%")
)

pie.set_global_opts(title_opts={"text": "销售额分布(嵌套饼图)"})

pie.render("nested_pie.html")

使用场景: 嵌套饼图适合显示“大类-小类“的层级关系,如“运动-球类、跑步、游泳“。

实践练习7:我的时间分配

任务: 制作一个嵌套饼图,显示你一天的时间分配:

内圈(大类):

  • 睡眠: 9小时
  • 上学: 8小时
  • 作业: 3小时
  • 娱乐: 4小时

外圈(娱乐细分):

  • 看电视: 1.5小时
  • 玩游戏: 1小时
  • 运动: 1小时
  • 其他: 0.5小时

答案:

点击查看完整代码
from pyecharts.charts import Pie
from pyecharts import options as opts

# 内圈: 大类
inner_data = [
    ("睡眠", 9), ("上学", 8), ("作业", 3), ("娱乐", 4)
]

# 外圈: 娱乐细分
outer_data = [
    ("看电视", 1.5), ("玩游戏", 1), ("运动", 1), ("其他", 0.5),
    # 补充其他类别的数据(为了图形完整)
    ("睡眠细分", 9), ("上学细分", 8), ("作业细分", 3)
]

pie = Pie()

pie.add(
    "",
    inner_data,
    radius=["0%", "35%"],
    label_opts=opts.LabelOpts(formatter="{b}: {c}小时")
)

pie.add(
    "",
    outer_data,
    radius=["45%", "70%"],
    label_opts=opts.LabelOpts(formatter="{b}: {c}小时")
)

pie.set_global_opts(title_opts={"text": "我的一天时间分配"})

pie.render("my_day_pie.html")

提示: 这个例子展示了嵌套饼图的应用,但外圈数据不完全对称,实际情况中可能需要更完整的数据分类。


15.6 综合项目:制作班级成绩分析报告

现在我们已经学会了柱状图、折线图、饼图,让我们做一个综合项目:班级成绩分析报告系统。

这个项目会综合运用我们学到的所有知识!

15.6.1 项目需求

假设你是班长,老师给你一份班级成绩数据,你需要:

  1. 柱状图显示每个学生的总分排名
  2. 折线图显示班级平均分的变化趋势
  3. 饼图显示各分数段的人数分布
  4. 生成一个完整的HTML报告

原始数据:

姓名语文数学英语物理化学
小明8592788890
小红9088959294
小刚7885828083
小丽9295889091
小华8890918589
小强8082857880
小芳9590929593

15.6.2 项目实现

让我们一步步完成这个项目:

步骤1: 准备数据

# 学生姓名
students = ["小明", "小红", "小刚", "小丽", "小华", "小强", "小芳"]

# 各科成绩
chinese = [85, 90, 78, 92, 88, 80, 95]
math = [92, 88, 85, 95, 90, 82, 90]
english = [78, 95, 82, 88, 91, 85, 92]
physics = [88, 92, 80, 90, 85, 78, 95]
chemistry = [90, 94, 83, 91, 89, 80, 93]

# 计算总分
total_scores = []
for i in range(len(students)):
    total = chinese[i] + math[i] + english[i] + physics[i] + chemistry[i]
    total_scores.append(total)

print("总分:", total_scores)

运行结果:

总分: [433, 459, 408, 456, 443, 405, 465]

步骤2: 柱状图 - 总分排名

from pyecharts.charts import Bar
from pyecharts import options as opts

# 创建柱状图
bar = Bar()

# 添加数据
bar.add_xaxis(students)
bar.add_yaxis(
    "总分",
    total_scores,
    label_opts=opts.LabelOpts(is_show=True)  # 显示数值
)

# 设置全局选项
bar.set_global_opts(
    title_opts={"text": "班级总分排名"},
    yaxis_opts=opts.AxisOpts(name="分数"),
    xaxis_opts=opts.AxisOpts(name="学生"),
    toolbox_opts=opts.ToolboxOpts(is_show=True)  # 显示工具栏
)

# 生成图表
bar.render("class_ranking.html")

步骤3: 折线图 - 科目平均分

from pyecharts.charts import Line

# 计算各科平均分
chinese_avg = sum(chinese) // len(chinese)
math_avg = sum(math) // len(math)
english_avg = sum(english) // len(english)
physics_avg = sum(physics) // len(physics)
chemistry_avg = sum(chemistry) // len(chemistry)

subjects = ["语文", "数学", "英语", "物理", "化学"]
avg_scores = [chinese_avg, math_avg, english_avg, physics_avg, chemistry_avg]

# 创建折线图
line = Line()

line.add_xaxis(subjects)
line.add_yaxis(
    "平均分",
    avg_scores,
    markpoint_opts=opts.MarkPointOpts(
        data=[
            opts.MarkPointItem(type_="max", name="最高分"),
            opts.MarkPointItem(type_="min", name="最低分")
        ]
    )
)

line.set_global_opts(
    title_opts={"text": "各科目平均分"},
    yaxis_opts=opts.AxisOpts(name="分数"),
    xaxis_opts=opts.AxisOpts(name="科目")
)

line.render("subject_averages.html")

步骤4: 饼图 - 分数段分布

from pyecharts.charts import Pie

# 统计分数段
ranges = ["优秀(90分以上)", "良好(80-89)", "及格(60-79)", "不及格(60分以下)"]
counts = [0, 0, 0, 0]

# 统计总分段
for score in total_scores:
    avg = score / 5  # 计算平均分
    if avg >= 90:
        counts[0] += 1
    elif avg >= 80:
        counts[1] += 1
    elif avg >= 60:
        counts[2] += 1
    else:
        counts[3] += 1

print("分数段分布:", counts)

# 创建饼图
pie = Pie()

pie.add(
    "",
    list(zip(ranges, counts)),
    radius=["30%", "60%"],
    label_opts=opts.LabelOpts(formatter="{b}: {c}人 ({d}%)")
)

pie.set_global_opts(title_opts={"text": "班级成绩分布"})

pie.render("score_distribution.html")

运行结果:

分数段分布: [3, 3, 1, 0]  # 优秀3人,良好3人,及格1人,不及格0人

步骤5: 组合所有图表

pyecharts提供了一个Page类,可以把多个图表组合在一个HTML页面:

from pyecharts.charts import Bar, Line, Pie
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode

# 数据准备(省略,参考上面的代码)

# 创建三个图表(代码省略)
bar = Bar()
# ... 添加数据和选项

line = Line()
# ... 添加数据和选项

pie = Pie()
# ... 添加数据和选项

# 组合图表
from pyecharts.charts import Page

page = Page(layout=Page.SimplePageLayout)

page.add(
    bar,
    line,
    pie
)

page.render("class_report.html")

运行结果: 打开class_report.html,你会看到三个图表从上到下排列在一个页面中,形成一个完整的成绩分析报告!

给家长的小贴士

  • 项目式学习: 这个综合项目能培养孩子的整体思维和问题解决能力
  • 数据收集: 鼓励孩子用真实数据(如自己班级的成绩)替换示例数据
  • 分析能力: 让孩子根据图表分析班级情况(如:哪科最难,谁进步最大)
  • 逐步完成: 强调分步骤完成,不要试图一次写完所有代码
  • 调试技巧: 如果某个图表有问题,单独运行它的代码,找出错误

综合练习8:完整的数据分析报告

任务: 选择一个你感兴趣的主题,制作一个完整的数据分析报告:

主题建议:

  1. 运动数据分析: 班级同学最喜欢的运动类型
  2. 游戏数据分析: 你和朋友的游戏等级、胜率、场次对比
  3. 零花钱分析: 一个月的零花钱来源和用途
  4. 阅读分析: 这学期读了多少本书,各类书的比例
  5. 自定义主题: 其他你感兴趣的数据

要求:

  1. 至少包含3种图表(柱状图、折线图、饼图)
  2. 每个图表都要有标题和坐标轴说明
  3. 用Page组合所有图表
  4. 根据图表写出3条分析结论

示例代码框架:

点击查看代码框架
from pyecharts.charts import Bar, Line, Pie
from pyecharts.charts import Page
from pyecharts import options as opts

# 步骤1: 准备数据
# TODO: 填写你的数据

# 步骤2: 创建柱状图
bar = Bar()
# TODO: 添加数据和选项

# 步骤3: 创建折线图
line = Line()
# TODO: 添加数据和选项

# 步骤4: 创建饼图
pie = Pie()
# TODO: 添加数据和选项

# 步骤5: 组合所有图表
page = Page()
page.add(bar, line, pie)
page.render("my_report.html")

print("报告已生成!")

15.7 进阶技巧:让图表更美观

15.7.1 使用主题

pyecharts提供了多种预设主题,可以快速改变图表的配色:

from pyecharts.charts import Bar
from pyecharts import options as opts
from pyecharts.globals import ThemeType

# 使用DARK主题
bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK))

bar.add_xaxis(["苹果", "香蕉", "橙子", "草莓", "葡萄"])
bar.add_yaxis("价格", [8, 3, 6, 15, 12])

bar.set_global_opts(title_opts={"text": "水果价格表"})

bar.render("themed_chart.html")

可用主题:

  • ThemeType.LIGHT: 浅色主题(默认)
  • ThemeType.DARK: 深色主题
  • ThemeType.ROMA: 罗马主题
  • ThemeType.SHINE: 闪亮主题
  • ThemeType.VINTAGE: 复古主题

15.7.2 自定义颜色

如果你想自定义图表的颜色,可以使用颜色列表:

from pyecharts.charts import Pie
from pyecharts import options as opts

items = ["篮球", "足球", "羽毛球", "乒乓球", "跑步", "游泳"]
counts = [15, 12, 8, 10, 6, 9]

pie = Pie()

pie.add(
    "",
    list(zip(items, counts)),
    # 自定义颜色
    color=["#FF6B6B", "#4ECDC4", "#45B7D1", "#FFA07A", "#98D8C8", "#F7DC6F"]
)

pie.set_global_opts(title_opts={"text": "班级运动喜好"})

pie.render("custom_colors.html")

颜色代码说明:

  • 使用十六进制颜色码(如#FF6B6B)
  • 可以在线搜索“hex color picker“选择颜色
  • 颜色列表长度应该与数据项数量一致

15.7.3 添加提示框和工具栏

from pyecharts.charts import Bar
from pyecharts import options as opts

bar = Bar()

bar.add_xaxis(["第一季度", "第二季度", "第三季度", "第四季度"])
bar.add_yaxis("销售额", [120, 200, 150, 180])

bar.set_global_opts(
    # 提示框配置
    tooltip_opts=opts.TooltipOpts(
        trigger="axis",  # 坐标轴触发
        axis_pointer_type="shadow"  # 阴影指示器
    ),
    # 工具栏配置
    toolbox_opts=opts.ToolboxOpts(
        is_show=True,
        feature={
            "saveAsImage": {},  # 保存为图片
            "dataView": {},     # 数据视图
            "restore": {}        # 还原
        }
    ),
    # 区域缩放
    datazoom_opts=opts.DataZoomOpts(is_show=True)
)

bar.render("advanced_features.html")

功能说明:

  • 提示框: 鼠标悬停时显示详细信息
  • 工具栏: 右上角显示保存、数据视图等工具
  • 区域缩放: 可以缩放查看部分数据

给家长的小贴士

  • 颜色搭配: 教孩子基本的配色原则(对比色、同类色)
  • 主题选择: 不同主题适合不同场合(如DARK适合夜间查看)
  • 功能叠加: 不要一次添加太多功能,会影响图表的可读性
  • 审美培养: 鼓励孩子尝试不同的配色,培养审美能力

15.8 常见错误和调试

15.8.1 数据类型错误

错误代码:

from pyecharts.charts import Bar

bar = Bar()
bar.add_xaxis("苹果")  # 错误:应该是列表
bar.add_yaxis("价格", 8)  # 错误:应该是列表

错误信息:

TypeError: Input x_axis data must be list

正确代码:

bar.add_xaxis(["苹果"])  # 使用列表
bar.add_yaxis("价格", [8])  # 使用列表

给家长的小贴士

  • 列表 vs 单个值: pyecharts需要列表,即使只有一个数据也要用[8]
  • 仔细阅读错误信息: 错误信息会明确告诉你是哪个参数有问题

15.8.2 数据长度不一致

错误代码:

bar.add_xaxis(["苹果", "香蕉", "橙子"])
bar.add_yaxis("价格", [8, 3])  # 只有2个数据,少了1个

错误信息:

AssertionError: x_axis data and y_axis data must be same length

解决方法: 确保x轴和y轴的数据数量一致:

bar.add_xaxis(["苹果", "香蕉", "橙子"])
bar.add_yaxis("价格", [8, 3, 6])  # 3个数据

15.8.3 文件路径错误

错误代码:

bar.render("C:\Users\用户名\桌面\chart.html")

错误信息:

SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes

原因: Python中\是转义字符,\U会被认为是Unicode转义。

解决方法1: 使用原始字符串

bar.render(r"C:\Users\用户名\桌面\chart.html")  # 注意r前缀

解决方法2: 使用正斜杠

bar.render("C:/Users/用户名/桌面/chart.html")  # 使用/

解决方法3: 只写文件名(推荐)

bar.render("chart.html")  # 保存到当前目录

给家长的小贴士

  • 路径问题: 小学生可能不理解文件路径,建议让他们只写文件名
  • 文件查找: 生成的HTML文件在当前工作目录,可以让孩子用文件管理器搜索
  • 桌面快捷方式: 在桌面上创建一个“我的图表“文件夹,方便查找

15.8.4 HTML文件打不开或空白

问题1: HTML文件打开后是空白页

原因: 代码运行时出现错误,但没有生成完整的HTML文件。

解决方法: 在Python中运行代码时,查看是否有错误提示。常见的错误:

  • 拼写错误:add_xasis应该是add_xaxis
  • 缺少括号或引号
  • 变量名未定义

问题2: 浏览器打不开HTML文件

原因: 浏览器太老,不支持某些特性。

解决方法: 更新浏览器或使用Chrome、Edge、Firefox等现代浏览器。

15.8.5 调试技巧

技巧1: 逐步验证

不要一次写完所有代码,而是分步测试:

# 步骤1: 测试数据
print("x轴:", ["苹果", "香蕉"])
print("y轴:", [8, 3])

# 步骤2: 测试图表创建
bar = Bar()
print("图表创建成功")

# 步骤3: 测试添加数据
bar.add_xaxis(["苹果", "香蕉"])
bar.add_yaxis("价格", [8, 3])
print("数据添加成功")

# 步骤4: 测试渲染
bar.render("test.html")
print("渲染完成")

技巧2: 简化数据

如果数据很复杂,先用简单数据测试:

# 复杂数据可能有1000条
# x_data = [...]  # 1000条
# y_data = [...]  # 1000条

# 先用3条数据测试
x_data = ["A", "B", "C"]
y_data = [1, 2, 3]

bar = Bar()
bar.add_xaxis(x_data)
bar.add_yaxis("测试", y_data)
bar.render("simple_test.html")

技巧3: 查看HTML源代码

如果图表显示不正常,用文本编辑器打开HTML文件,搜索"code":

<script>
  var chart = echarts.init(...);
  var option = {
    "title": {...},
    "tooltip": {...},
    ...
  };
  chart.setOption(option);
</script>

查看是否有"error""undefined"等异常信息。

给家长的小贴士

  • 调试思维: 教孩子“分而治之“的调试方法,把大问题拆成小问题
  • 错误是朋友: 强调错误信息是帮助我们解决问题的线索
  • 保存中间版本: 鼓励孩子定期保存代码的备份,出错时可以回退

15.9 本章小结

15.9.1 核心知识点回顾

1. 数据可视化的重要性

  • 把抽象的数字变成直观的图形
  • 让数据更容易理解和分析
  • 帮助发现数据背后的规律

2. pyecharts库的使用流程

安装: pip install pyecharts
  ↓
导入: from pyecharts.charts import Bar
  ↓
创建: bar = Bar()
  ↓
数据: bar.add_xaxis() / bar.add_yaxis()
  ↓
选项: bar.set_global_opts()
  ↓
渲染: bar.render("file.html")

3. 三种常见图表

图表类型用途适合场景
柱状图比较不同类别排名、对比、统计
折线图显示变化趋势成绩进步、气温变化、股票走势
饼图显示比例关系费用分配、偏好分布、成分构成

4. 图表的配置选项

  • 标题: title_opts
  • 坐标轴: xaxis_opts / yaxis_opts
  • 标签: label_opts
  • 图例: legend_opts
  • 工具栏: toolbox_opts
  • 提示框: tooltip_opts

5. 高级功能

  • 多系列: 在一个图表上显示多组数据
  • 堆叠: 堆叠柱状图显示部分与整体
  • 嵌套: 嵌套饼图显示层级关系
  • 组合: 用Page组合多个图表

15.9.2 能力检查表

请孩子自我检查以下技能是否掌握:

  • 能独立安装pyecharts库
  • 能创建并保存一个简单的柱状图
  • 能创建并保存一个简单的折线图
  • 能创建并保存一个简单的饼图
  • 能为图表添加标题和坐标轴说明
  • 能在一个图表上显示多组数据
  • 能使用Page组合多个图表
  • 能读懂简单的错误信息并调试
  • 能独立完成一个数据分析小项目

15.9.3 常见问题快速参考

问题解决方法
安装失败使用国内镜像源:pip install pyecharts -i https://pypi.tuna.tsinghua.edu.cn/simple
中文乱码在文件第一行添加# -*- coding: utf-8 -*-
数据长度不一致检查x轴和y轴的数据数量是否相同
HTML文件找不到只写文件名(如chart.html),保存到当前目录
图表空白检查浏览器,使用Chrome或Edge等现代浏览器

15.10 挑战练习

挑战1: 天气数据分析

任务: 从网上查找你所在城市最近一周的天气数据(最高气温、最低气温、天气状况),制作:

  1. 折线图:显示气温变化
  2. 饼图:显示不同天气状况的比例(如:晴天3天,阴天2天,雨天2天)

要求:

  • 使用真实数据
  • 图表有标题和说明
  • 添加数据标记点(最高温、最低温)

挑战2: 我的学习时间统计

任务: 记录自己一周每天的学习时间,制作:

  1. 柱状图:显示每天的学习时长
  2. 饼图:显示学习时间的分配(如:周一2小时,周二3小时…)

要求:

  • 数据真实可靠
  • 分析哪天学习时间最长/最短
  • 找出学习规律并给出建议

挑战3: 游戏数据分析

任务: 如果你有喜欢的游戏,记录游戏数据,制作:

  1. 柱状图:你和朋友的等级对比
  2. 折线图:最近10次的胜率变化
  3. 饼图:使用英雄/武器的频率

要求:

  • 至少包含3种图表
  • 用Page组合所有图表
  • 写出分析结论(如:我最擅长哪个英雄)

挑战4: 班级调查报告

任务: 设计一个班级调查(如:最喜欢的科目、最喜欢的运动、每天的学习时间…),收集数据后制作完整的分析报告。

要求:

  • 调查至少10名同学
  • 使用柱状图、折线图、饼图
  • 报告包含:
    • 调查主题
    • 数据来源
    • 图表分析
    • 你的建议

挑战5: 创意数据可视化

任务: 选择一个你感兴趣的主题(如:我的阅读记录、零花钱追踪、运动数据分析…),制作一个创意数据可视化项目。

要求:

  • 数据真实且有连续性(至少记录一周)
  • 至少3个图表
  • 尝试使用主题、自定义颜色等高级功能
  • 向同学展示你的报告,并收集反馈

15.11 下一步预告

恭喜你完成了第15章的学习!你已经掌握了:

  • ✅ 数据可视化的基本概念
  • ✅ 柱状图、折线图、饼图的制作
  • ✅ pyecharts库的使用方法
  • ✅ 完整的数据分析报告制作

第16章:图形程序中,你将学习:

  • 使用tkinter库创建图形界面
  • 按钮、文本框、标签等控件
  • 制作带界面的交互程序

想象一下,不再是在黑色的命令行窗口输入命令,而是有漂亮的窗口、按钮、输入框…这就是图形界面的魅力!我们下一章见!


附录:pyecharts速查表

常用图表类

from pyecharts.charts import Bar, Line, Pie

# 柱状图
bar = Bar()
bar.add_xaxis(x_data)
bar.add_yaxis(series_name, y_data)
bar.render("bar.html")

# 折线图
line = Line()
line.add_xaxis(x_data)
line.add_yaxis(series_name, y_data)
line.render("line.html")

# 饼图
pie = Pie()
pie.add(series_name, data)
pie.render("pie.html")

常用配置选项

from pyecharts import options as opts

# 标题
title_opts={"text": "图表标题"}

# 坐标轴
xaxis_opts=opts.AxisOpts(name="x轴名称")
yaxis_opts=opts.AxisOpts(name="y轴名称")

# 标签
label_opts=opts.LabelOpts(is_show=True)  # 显示数据标签

# 提示框
tooltip_opts=opts.TooltipOpts(trigger="axis")

# 工具栏
toolbox_opts=opts.ToolboxOpts(is_show=True)

# 数据缩放
datazoom_opts=opts.DataZoomOpts(is_show=True)

常用主题

from pyecharts.globals import ThemeType

bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK))
bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.ROMA))
bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.SHINE))

Page组合图表

from pyecharts.charts import Page

page = Page()
page.add(chart1, chart2, chart3)
page.render("combined.html")

祝贺你完成第15章的学习! 🎉

现在,你已经能用Python制作专业的数据报表了!试试用你学到的技能,记录和分析生活中的数据吧!