0
点赞
收藏
分享

微信扫一扫

场景编程集锦 - 斗茶

场景描述

  “2022年全国名优茶品质大赛”(也称为斗茶大赛) 于6月18日在山城重庆举行,来自全国50多家茶叶生产厂商参赛观摩。本届茶叶品质评审委员会是从国家专家库中随机抽取的8名茶叶审评专家组成。大赛将产生全国名优质茶金奖1名,银奖2名,铜奖3名。具体的比赛规则如下:

评审指标

评审指标共计9个。其中干评指标有:嫩度、色泽、条索、整碎、 净度等5个;湿评指标则是香气、 汤色、滋味和叶底4项指标。

指标分值

嫩度(10)、色泽(10)、条索(10)、整碎(10)、净度(10)、香气(15)、汤色(10)、滋味(15)、叶底(10),9项指标总分为100分。

指标权重

指标权重分配如下:嫩度(0.10)、色泽(0.05)、条索(0.05)、整碎(0.05)、净度(0.05)、香气(0.25)、汤色(0.10)、滋味(0.25)、叶底(0.10)

专家评审

每位专家需要对参评的20种茶叶的9项指标进行评分。表格样式如下所示: image.png

综合得分

每种茶叶的综合得分按照以下公式计算:

$score =\sum^9_{n=1}(a_nb_n )$ 其中$n$取值$1-9$,代表$9$个评审指标编号;$a_n$代表指标$n$对应的权重;$b_n$代表所有专家对某种茶叶的指标$n$评分之和(需要去掉一个最高分和一个最低分),$score$代表某种茶叶的综合得分。 下面我们将使用Python编程的解决方案,实现评审数据采集,茶叶综合得分计算以及生成茶叶评比的排行榜。

编程思路

评审打分

采用Excel文件作为专家评分表,每位专家均要为参赛的20个茶样进行评分,每个茶样需要对9个指标逐一进行评分。

指标权重

本届茶叶品质大赛设立了9个评审指标,每个指标的权重设置如下所示。我们采用文本文件weight.txt方式保存,具体内容包括:

嫩度 0.10 色泽 0.05 条索 0.05 整碎 0.05 净度 0.05 香气 0.25 汤色 0.10 滋味 0.25 叶底 0.10

其中:指标名称与权重值之间是以’\t’制表符进行分隔。 在Windows环境下,我使用notepad记事本程序来创建文本文件weight.txt,在此需要特别说明的是保存文件要指定文件格式UTF-8,以便与本案例中的读取权重文件的函数配套使用。

数据采集

Python提供了多种方式可以访问和读取微软的Excel文件,本案例选用pandas模块读取专家Excel文件的评分表,将评审表内容以dataframe形式存放,供后续处理。

计算综合得分

我们需要读取所有评审专家的评分表,针对每个参赛茶样,汇总合计每一个指标的专家评审分值,同时在这个过程中需要去除一个最高分和一个最低分,根据综合得分计算公式,求出该茶叶品种的综合得分。

生成排行榜

根据所有茶叶品种的综合得分进行排名,显示或打印“2022年全国名优茶排行榜”和“2022年全国名优茶获奖名单”。

代码实现

程序代码

"""
  tea_competition.py : 打望全国名优茶品质大赛
"""
import os
import pandas as pd

def main():
    weight = get_weight('data/weight.txt')
    all_xls = get_xls('data')
    total_df = concat_df(all_xls)

    rank = get_rank(total_df, weight)

    print_rank(rank)
    print_prizes(rank)

def get_weight(file):
    """
    获取评审指标权重因子
    """
    indicators = {}
    with open(file, encoding='utf-8') as f:
        lines = f.readlines()
        for line in lines:
            name, weight = line.strip().split('\t')   # ①
            indicators[name] = float(weight)
    return indicators

def get_xls(dirname):
    """
    获取评审表文件名的列表
    """
    all_xls = os.listdir(dirname)
    all_xls = [dirname+'/'+f for f in all_xls if f.endswith('xlsx')]   # ②
    return all_xls

def concat_df(all_xls):
    """
    功能:多个 dataframe 拼接
    """
    for i, xls in enumerate(all_xls):
        df = pd.read_excel(xls, header=3, index_col=0)   # ③
        df = df.iloc[:-1]
        if i == 0:
            total = df
        else:
            total = pd.concat([total, df])    # ④
    return total

def get_rank(total_df, weight):
    """
    功能:按照茶叶种类,分别计算综合得分
    """
    indicators = list(total_df.columns)   # ⑤
    tea_type = set(total_df.index)  # ⑥ 

    rank = []
    for tea in tea_type:
        scores = 0
        df = total_df.loc[tea]   # ⑦

        for indicator in indicators:
            score_lst = list(df[indicator])  # ⑧ 
            score_lst.sort()
            score_lst = score_lst[1:-1]   # ⑨ 
            score = sum(score_lst)
            scores += score * weight[indicator]
        rank += [(tea, round(scores, 1))]

    rank.sort(key=lambda e: e[1], reverse=True)   # ⑩
    return rank

def print_rank(rank):
    """
    功能: 打印评审结果排行榜
    """
    print('--- 2022全国名优茶排行榜 ---')
    for i, (tea, score) in enumerate(rank):
        print(str(i+1).ljust(3), tea, '\t', str(score).rjust(10))

def print_prizes(rank):
    """
    功能:打印获奖名单
    """
    print('\n*** 2022全国名优茶获奖名单 ***\n')
    print('金奖:' + rank[0][0])
    print('银奖:' + rank[1][0] + '\t' + rank[2][0])
    print('铜奖:', end='')
    for tea, score in rank[3:6]:
        print(tea, end='\t')
    print()

if __name__ == '__main__':
    main()

主要函数

函数get_weight():读取文本文件weight.txt,获取评审指标的权重因子,返回权重因子字典。 函数get_xls():获取所有的专家评审电子表格文件名,返回值为包含文件名的列表。 函数concat_df():读入所有专家评审表Excel文件,实现表格数据拼接。其返回值是一个pandas的dataframe数据结构,其中包含了所有专家的评审表数据。 函数get_rank():这是最重要的功能实现。按照茶叶品名分类,分别计算其综合得分。返回值按照综合得分降序排列的排行榜列表,而列表中的每一个元素又是一个元组,包含茶叶品名和综合得分。 函数print_rank():打印评审结果的排行榜。 函数print_prizes():打印获奖名单。 函数main():主程序,整个代码的主入口。

重要语句

语句①解包元组,分离指标名和权重值。 语句②使用列表推导式生成评审表文件名列表。 语句③读入Excel文件内容,生成dataframe数据结构存储评审表数据。 语句④实现多个dataframe数据结构的连接(拼接)操作,简单明了。 语句⑤获取dataframe结构列名,强制转换为列表,其中包含了9个评审指标名称。 语句⑥获取茶叶品名的集合。通过使用集合set,实现除去重复值的功能。 语句⑦按照茶叶品名,获取所有专家的指标评分,它是一个8X9的矩阵数据,8代表8位评审专家,9代表9项指标。 语句⑧获取所有评审专家对1个茶叶品名和1个指标的评分值,这是生成了一个列表。 语句⑨去除一个最高分和一个最低分,代码极其简洁。 语句⑩实现列表排序。由于列表的每个元素是一个元组,排序的键是元组的第2个元素,代表茶叶品名对应的综合得分,通过函数参数key=lambda e: e[1] 指定排序键,参数reverse=True代表按降序排序。

运行效果

环境安装

本程序运行环境需要安装pandas和openpyxl模块。可以在Windows的命令行窗口中执行以下命令完成模块安装。

pip install pandas -i http://pypi.douban.com/simple --trusted-host pypi.douban.com pip install openpyxl -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

目录结构

本程序由代码文件tea_competition.py和数据文件组成。数据文件存放在子目录data下面,weight.txt为指标权重文件,余下的是专家评审的Excel电子表格文件,这些数据均为模拟数据。

D:\cases\斗茶 tea_competition.py
D:\cases\斗茶\data weight.txt 万沐春.xlsx 吕静成.xlsx 张冲之.xlsx 李博闻.xlsx 李拓.xlsx 柳湘莲.xlsx 周立可.xlsx 邱荷.xlsx

程序执行

image.png

程序优化

  截止目前,我们所编程的程序已经完美地实现了业务需求,程序代码简洁,实现逻辑清晰,功能非常强的。如果要使用其他编程语言实现相同的功能,其代码编程量是目前编程量的3~5倍。可见Python的编程效率是相当的高效。   在本案例程序的实现中,为了获取正确的评审结果,有一个相当重要的前提是假定专家评审数据是正确的。如果某位专家对某茶样的“嫩度”指标的评分为13分,这是一个无效分,因为该指标的高分为10分。为了正确程序的容错能力,我们需要对专家的评分表进行数据有效性检测。根据评分规则,每一个指标设定了最高分,那么最低分是否就是零,这一点需要明确;当然也可以结合实际情况,是否需要设置每一个指标的起评分,这也是一种解决方案。   好了,我们已经了解了每一个评审指标的最高分和最低分范围,就可以轻松地编写数据有效性检测程序。这个程序有点小挑战,有兴趣的读者可以自行编写。

场景扩展

  本案例场景解决方案还适用于:企业绩效考核指标评分与统计、蔬菜水果质量评审、饮料品质评审、白酒/红酒品质评审、咖啡品鉴会等应用场景。

举报

相关推荐

0 条评论