Python自动化办公 / 实例:体测成绩自动化打分

目录

前提

代码分步解说

加载原始数据

空值 重复值 

1000米打分 

50米打分

跳远打分 

肺活量打分 

BMI指标 

一键运行

优化操作

总结


语言:python

工具:jupyter


前提

所需要导入的库有

  • numpy
  • pandas

代码分步解说

首先导入库,并重命名

#numpy运算库 矩阵
import numpy as np

#pandas 做业务表格处理
import pandas as pd

加载原始数据

 读取表18级高一体测记录.xlsx

records = pd.read_excel(r'C:\Users\1\Desktop\18级高一体测记录汇总.xlsx')
#可直接用records进行输出jupyter默认的
#head默认显示表格前5行
records.head()'C:\Users\1\Desktop\18级高一体测记录汇总.xlsx')

 

 读取打分标准表(体测评分标准)

score_table = pd.read_excel(r'C:\Users\1\Desktop\体测评分标准.xlsx',header=[0,1],index_col=[0])
#header=[0,1] 将前两行进行固定 ;index_col=[0]将第一行进行 行索引
score_table.head()

 

空值 重复值 

 判断空值isnull()求均值mean();

#先判断是否空值isnull();再求均值,即求每一列的True的均值mean()
#Fasle 0;  True 1;
records.isnull().mean()

 可以看到当列表中有空值的时候,返回True。再求均值就可以看到哪一些中是有空值存在,由此进行判断。

 

 在上一步中我们判断出表格中有空值,所以现在我们对它进行填充,对所有空格进行0值填充。

填充fillna()

records = records.fillna(0)
records

 

再进行验证一下,可以看到空值不见了,已经被0值填充。 

records.isnull().mean()

 

表格数据类型数据处理 records.info()

我们先是对表格信息进行查询,如下所示

 

 要知道分数中的分秒不好识别比较易出错,所以我们把它转换为数值,如下所示

def transformer(time_obj):
    if isinstance (time_obj,str):    #用isinstance来判断是否为字符串类型
        minute,seconds = time_obj.split("'")
        return int(minute)+int(seconds)/60
    else:
        return 0


records['1000米'] = records['1000米'].map(transformer)
records

 

1000米打分 

 第一步:去除score_table中的1000米成绩的时间类型中的多余部分,并转换成普通数值。

def strip_fh(x):
    return x.strip('"')


score_table[('1000米','成绩')] = score_table[('1000米','成绩')].map(strip_fh)
score_table[('1000米','成绩')] = score_table[('1000米','成绩')].map(transformer)
score_table

我们可以看到,体测评分标准 中的1000米成绩变成了数值部分而不是分秒。

 

第二步:提取1000米成绩 

#提取1000米成绩
m_1000 = score_table['1000米']

def calculate(x):
    if x == 0:
        return 0
    select = x <= m_1000['成绩']
    if select.sum() <= 0:
        return 0
    return m_1000.loc[select,'分数'].iloc[0]

 第三步:运行

records['1000米分数'] = records['1000米'].map(calculate)
records

可以看到在最后一列,‘1000米分数’  运行评分成功。 

 

 同理

50米打分

#提取50米成绩
m_50 = score_table['50米']

def calculate_50(x):
    if x == 0:
        return 0
    select = x <= m_50['成绩']
    if select.sum() <= 0:
        return 0
    return m_50.loc[select,'分数'].iloc[0]

records['50米分数'] = records['50米'].map(calculate_50)
records

 

跳远打分 

由于跳远打分是数值越大分越高,所以 select = x >= far_score

#提取跳远成绩
far_score = score_table['跳远']

def calculate_far(x):
    if x == 0:
        return 0
    select = x >= far_score['成绩']
    if select.sum() <= 0:
        return 0
    return far_score.loc[select,'分数'].iloc[0]

records['跳远分数'] = records['跳远'].map(calculate_far)
records

 

肺活量打分 

#提取肺活量成绩
live_score = score_table['肺活量']

def calculate_live(x):
    if x == 0:
        return 0
    select = x >= live_score['成绩']
    if select.sum() <= 0:
        return 0
    return live_score.loc[select,'分数'].iloc[0]

records['肺活量成绩'] = records['肺活量'].map(calculate_live)
records

BMI指标 

#KG/M^2
M2 = (records['身高']/100)**2
KG = records['体重']
BMI = KG/M2
records['BMI']=BMI
records


一键运行

#封装一个转换时间类型的函数  解决1000米 50米问题
def transformer(time_obj):
    if isinstance (time_obj,str):    #用isinstance来判断是否为字符串类型
        minute,seconds = time_obj.split("'")
        return int(minute)+int(seconds)/60
    else:
        return 0

#去除score_table中的1000米成绩的时间类型中的多余部分
def strip_fh(x):
    return x.strip('"')

#1000米打分映射逻辑
m_1000 = score_table['1000米']

def calculate(x):
    if x == 0:
        return 0
    select = x <= m_1000['成绩']
    if select.sum() <= 0:
        return 0
    return m_1000.loc[select,'分数'].iloc[0]

#50米打分映射逻辑
m_50 = score_table['50米']

def calculate_50(x):
    if x == 0:
        return 0
    select = x <= m_50['成绩']
    if select.sum() <= 0:
        return 0
    return m_50.loc[select,'分数'].iloc[0]

#跳远打分映射逻辑
far_score = score_table['跳远']

def calculate_far(x):
    if x == 0:
        return 0
    select = x > far_score['成绩']
    if select.sum() <= 0:
        return 0
    return far_score.loc[select,'分数'].iloc[0]


#肺活量打分映射逻辑
live_score = score_table['肺活量']

def calculate_live(x):
    if x == 0:
        return 0
    select = x > live_score['成绩']
    if select.sum() <= 0:
        return 0
    return live_score.loc[select,'分数'].iloc[0]

#传入两个路径
def main_logic(records_path,score_table_path):
    #加载原始数据
    records = pd.read_excel(records_path)
    score_table = pd.read_excel(score_table_path,header=[0,1],index_col=[0])
    
    #对空值处理
    records = records.fillna(0)
    
    #对记录表中的1000米进行时间类型转换
    records['1000米'] = records['1000米'].map(transformer)
    
    #去除1000米成绩的时间类型中的多余部分
    score_table[('1000米','成绩')] = score_table[('1000米','成绩')].map(strip_fh)
    
    #对记录表中的1000米做时间类型做转换
    score_table[('1000米','成绩')] = score_table[('1000米','成绩')].map(transformer)
    
    #1000米打分
    records['1000米分数'] = records['1000米'].map(calculate)
    
    #50米打分
    records['50米分数'] = records['50米'].map(calculate_50)
    
    #跳远打分
    records['跳远分数'] = records['跳远'].map(calculate_far)
    
    #肺活量
    records['肺活量成绩'] = records['肺活量'].map(calculate_live)
    
    #BMI
    M2 = (records['身高']/100)**2
    KG = records['体重']
    records['BMI']= KG/M2

#运行
main_logic(r'C:\Users\1\Desktop\18级高一体测记录汇总.xlsx',r'C:\Users\1\Desktop\体测评分标准.xlsx')
records

 结果输出图:


优化操作

 因为上一个的一键操作中有许多重复相似的用法,所以可以对它进行进一步的优化。可以看到这个优化解决了公式的通用重复和4列数据的映射途径,大大缩减了代码的行数节省了空间,时间。

#封装一个转换时间类型的函数  解决1000米 50米问题
def transformer(time_obj):
    if isinstance (time_obj,str):    #用isinstance来判断是否为字符串类型
        minute,seconds = time_obj.split("'")
        return int(minute)+int(seconds)/60
    else:
        return 0

#去除score_table中的1000米成绩的时间类型中的多余部分
def strip_fh(x):
    return x.strip('"')

def calculate_normal(x,flag):
   #判断空值(被填充为0的值,是缺考,所以直接给0分)
    if x == 0:
        return 0
    #判断是越大分越高(跳远、肺活量),还是越小分越高(50米、1000米)
    if flag == True:
        select = x <= m_1000['成绩']
    else:
        select = x > m_1000['成绩']
        
    if select.sum() <= 0:
        return 0
    
    return m_1000.loc[select,'分数'].iloc[0]

#传入两个路径
def main_logic(records_path,score_table_path):
    #加载原始数据
    records = pd.read_excel(records_path)
    score_table = pd.read_excel(score_table_path,header=[0,1],index_col=[0])    
    #对空值处理
    records = records.fillna(0)   
    #对记录表中的1000米进行时间类型转换
    records['1000米'] = records['1000米'].map(transformer)   
    #去除1000米成绩的时间类型中的多余部分
    score_table[('1000米','成绩')] = score_table[('1000米','成绩')].map(strip_fh)   
    #对记录表中的1000米做时间类型做转换
    score_table[('1000米','成绩')] = score_table[('1000米','成绩')].map(transformer)  

    
    #解决4列数据的映射途径
    columns = ['1000米','50米','跳远','肺活量']
    for col in columns:
        flag_data = col in ['1000米分数','50米分数']
        #caculate_normal函数,是一个通用的映射函数,用来打分
        records[col+'分数'] = records[col].apply(calculate_normal,flag=flag_data)
 
    #BMI
    M2 = (records['身高']/100)**2
    KG = records['体重']
    records['BMI']= KG/M2

#运行
main_logic(r'C:\Users\1\Desktop\18级高一体测记录汇总.xlsx',r'C:\Users\1\Desktop\体测评分标准.xlsx')
records

 结果输出图:


 

总结

这一部分虽然看着很多,其实后面都是对前面的的分步进行总结、升华。先将分步的代码掌握好也是非常重要的,不要想着一口能吃成大胖子。然后再将分步中的代码结合起来,做到完整收纳融合。最后,才开始去想如何提升自己的代码,做进一步的升华,这样才能做到事半功倍。

等我们啥时候打够10000行代码后,我们的熟练度也会不断提升的,让我们一起加油吧。今天这一篇更了五千多字,好累啊!所以看到这里的友友觉得有用就点个赞吧,你的赞将是我的动力

o(* ̄▽ ̄*)ブ加油!加油!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五彩大铁猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值