003《Python数据分析、挖掘与可视化(第2版)》/例9-8_1.py
from itertools import groupby
import matplotlib.pyplot as plt

# 设置图形中使用中文字体
plt.rcParams['font.sans-serif'] = ['simhei']

# 每门课程的成绩
scores = {'数据结构':[89,70,49,87,92,84,73,71,78,81,90,37,
                     77,82,81,79,80,82,75,90,54,80,70,68,61],
          '线性代数':[70,74,80,60,50,87,68,77,95,80,79,74,
                     69,64,82,81,78,90,78,79,72,69,45,70,70],
          '英语':[83,87,69,55,80,89,96,81,83,90,54,70,79,
                  66,85,82,88,76,60,80,75,83,75,70,20],
          'Python':[90,60,82,79,88,92,85,87,89,71,45,50,
                    80,81,87,93,80,70,68,65,85,89,80,72,75]}

# 自定义分组函数,在下面的groupby()函数中使用
def splitScore(score):
    if score >= 85:
        return '优'
    elif score >= 60:
        return '及格'
    else:
        return '不及格'
    
# 统计每门课程中优、及格、不及格的人数
# ratios的格式为{'课程名称':{'优':3, '及格':5, '不及格':1},...}
ratios = dict()
for subject, subjectScore in scores.items():
    ratios[subject] = {}
    # groupby()函数需要对原始分数进行排序才能正确分类
    for category, num in groupby(sorted(subjectScore), splitScore):
        ratios[subject][category] = len(tuple(num))
print(ratios)

# 创建4个子图
fig, axs = plt.subplots(2, 2)
axs.shape = 1,4
# 依次在4个子图中绘制每门课程的饼状图
for index, subjectData in enumerate(ratios.items()):
    # 选择子图
    plt.sca(axs[0][index])
    subjectName, subjectRatio = subjectData
    plt.pie(list(subjectRatio.values()),        # 每个扇形对应的数
            labels=list(subjectRatio.keys()),   # 每个扇形的标签
            explode=(0, 0, 0.2),
            pctdistance=0.7, shadow=True,
            autopct='%1.1f%%')                  # 百分比显示格式
    plt.xlabel(subjectName)
    plt.legend()
    # plt.gca().set_aspect('equal')
plt.show()