Matplotlib 高级柱状图绘制挑战:电影票房分析
题目要求
你需要使用 Matplotlib 绘制一个详细的三部电影在三天内的票房对比分析图。这个练习将考验你对 Matplotlib 各个细节的掌握程度。
数据
三部电影:《星际穿越》、《盗梦空间》、《黑暗骑士》
三天票房数据(单位:万元):
| 电影 | 第一天 | 第二天 | 第三天 |
|---|---|---|---|
| 星际穿越 | 1250 | 1180 | 980 |
| 盗梦空间 | 980 | 1120 | 1350 |
| 黑暗骑士 | 1100 | 1050 | 1150 |
具体要求
1. 基础图形设置
- 创建图形和子图,设置合适的大小
- 设置中文字体支持,确保中文正常显示
- 解决负号显示问题
2. 柱状图绘制
- 使用分组柱状图,确保三部电影在每一天的柱子并排显示
- 为每部电影设置不同的颜色和纹理模式
- 控制柱子的宽度和间距,使其美观且易读
3. 坐标轴和脊柱定制
- 设置合适的 X 轴和 Y 轴范围
- 自定义 Y 轴刻度格式(如添加"万"单位)
- 隐藏顶部和右侧脊柱,只保留底部和左侧脊柱
- 调整左侧脊柱位置,使其从零点开始
4. 标签和标题
- 添加主标题和子标题
- 设置 X 轴和 Y 轴标签
- 添加图例,并自定义其位置和样式
- 在柱子顶部显示具体的票房数值
5. 网格和样式
- 添加主要和次要网格线
- 设置网格线样式(颜色、线型、透明度)
- 自定义刻度标签的字体大小和旋转角度
6. 高级功能
- 在图表中添加票房趋势线(用折线连接同部电影三天的数据点)
- 添加数据标签说明总票房最高的电影
- 使用颜色渐变或阴影效果增强视觉层次
- 添加自定义注解或箭头指向关键数据点
7. 输出和保存
- 调整图形布局,确保所有元素都完整显示
- 保存为高分辨率 PNG 文件
- 在代码中添加详细注释说明每一步的作用
额外挑战
- 创建一个子图,在主图下方显示三部电影三天票房的总和对比
- 在柱状图背景中添加票房目标的参考线
- 实现交互式提示(使用
mplcursors或类似库) - 自定义颜色主题,使用非默认配色方案
提示:这个题目涵盖了 Matplotlib 的大部分核心功能,包括图形创建、数据可视化、样式定制、文本标注和高级布局。通过完成这个练习,你将全面掌握 Matplotlib 的各个细节。
代码如下:
import matplotlib.pyplot as plt
import numpy as npplt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=Falsedays = ['第一天', '第二天', '第三天']
y_xj = [1250, 1180, 980]
y_dm = [980, 1120, 1350]
y_dark = [1100, 1050, 1150]fig, ax = plt.subplots(figsize = (12, 8))
x = np.array([0, 1, 2])
width = 0.25bars1 = ax.bar(x - width, y_xj, width, color='pink', label='星际穿越', alpha=0.8)
bars2 = ax.bar(x, y_dm, width, color='red', label='盗梦空间', alpha=0.8)
bars3 = ax.bar(x + width, y_dark, width, color='green', label='黑暗骑士', alpha=0.8)for bars in [bars1, bars2, bars3]:for bar in bars:ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 20, f'{bar.get_height()}', ha='center', va='bottom')ax.set_xlabel('上映天数')
ax.set_ylabel('票房(万元)')
ax.set_title('三日票房统计')ax.set_xticks(x)
ax.set_xticklabels(days)ax.grid(linestyle='--')ax.plot(x-width, y_xj)
ax.scatter(x-width, y_xj)
ax.plot(x, y_dm)
ax.scatter(x, y_dm)
ax.plot(x+width, y_dark, color='red')
ax.scatter(x+width, y_dark, color='red')
plt.tight_layout()
plt.show()
