Python+Excel數(shù)據(jù)分析實(shí)戰(zhàn):軍事體能考核成績(jī)?cè)u(píng)定(三)男子引體向上計(jì)算

一、基本情況

通過分析男子引體向上“成績(jī)計(jì)算標(biāo)準(zhǔn)表”,發(fā)現(xiàn)標(biāo)準(zhǔn)表只是參照標(biāo)準(zhǔn)表,不是連續(xù)的全覆蓋,比如標(biāo)準(zhǔn)中24歲以下,只規(guī)定了單桿30個(gè)100分,27個(gè)95分,那么28/29個(gè)的情況多少分呢?

男子引體向上成績(jī)計(jì)算標(biāo)準(zhǔn)表

只能是我們根據(jù)公平原則去補(bǔ)充,在30/27之間去取平均分,數(shù)據(jù)量比較小,為加快程序運(yùn)行速度,我選擇手工計(jì)算,補(bǔ)充到成績(jī)計(jì)算標(biāo)準(zhǔn)表里,精確到小數(shù)點(diǎn)后一位。


男子單杠補(bǔ)充標(biāo)準(zhǔn)表

當(dāng)然根據(jù)標(biāo)準(zhǔn),40歲以上組織俯臥撐考核替代引體向上考核。


男子俯臥撐補(bǔ)充標(biāo)準(zhǔn)表

按照上一章Python+Excel數(shù)據(jù)分析實(shí)戰(zhàn):軍事體能考核成績(jī)?cè)u(píng)定(二)基本框架和年齡計(jì)算中的算法思路,制作完成績(jī)計(jì)算標(biāo)準(zhǔn)表后,通過Python的openpyxl模塊讀取補(bǔ)充成績(jī)計(jì)算標(biāo)準(zhǔn)表中的數(shù)據(jù),制成 {原始單杠個(gè)數(shù):分?jǐn)?shù)} 格式的字典,以供主程序查詢出換算成績(jī),再寫入成績(jī)表的對(duì)應(yīng)位置中。

為什么要選擇字典類型呢?這也是為什么選擇Python語言的原因:

Python具有語法簡(jiǎn)潔、簡(jiǎn)單易學(xué)、代碼高效、功能強(qiáng)大的特點(diǎn),我個(gè)人認(rèn)為,這要?dú)w功于列表(list)、字典(dict)、元組(tuple)和集合(set)這“四大金剛”。盡管整型(int)、浮點(diǎn)型(float)和字符串(str)也很重要,但這三種對(duì)象相對(duì)于其他編程語言來說,差異并不像“四大金剛”那樣明顯。可以毫不夸張地說,列表、字典、元組和集合代表了Python語言的核心和基礎(chǔ),同時(shí)也是Python的精髓所在。學(xué)會(huì)使用列表、字典、元組和集合,就意味著掌握了Python這門編程語言。

字典(dict)是Python用于存放具有映射關(guān)系的數(shù)據(jù),相當(dāng)于保存了兩組數(shù)據(jù),其中一組數(shù)據(jù)是關(guān)鍵數(shù)據(jù),被稱為 key;另一組數(shù)據(jù)可通過 key 來訪問,被稱為 value。列表是根據(jù)偏移量來讀取的,而字典是根據(jù)鍵的Hash來讀取的,字典的索引效率要遠(yuǎn)遠(yuǎn)大于列表。

從Python 3.6開始,字典是變成有順序的了。你先插入鍵值對(duì)A,后插入鍵值對(duì)B,那么當(dāng)你打印Keys列表的時(shí)候,你就會(huì)發(fā)現(xiàn)B在A的后面。這樣使得索引的效率更高,而且后面計(jì)算3000米跑時(shí),因數(shù)據(jù)太多不能手動(dòng)補(bǔ)充標(biāo)準(zhǔn)數(shù)據(jù)時(shí),要利用這個(gè)有序的特性,進(jìn)行計(jì)算。

所以我設(shè)計(jì)了{(lán)原始單杠個(gè)數(shù)(key):分?jǐn)?shù)(value)} 這樣的字典格式來查詢對(duì)應(yīng)的分?jǐn)?shù)。

二、代碼實(shí)現(xiàn)

男子引體向上原始表

1.計(jì)算男子引體向上的模塊我命名為pullup_standard_data.py,首先是讀取出標(biāo)準(zhǔn)數(shù)據(jù),制成 {原始單杠個(gè)數(shù):分?jǐn)?shù)} 格式的字典。每一個(gè)字典是分年齡段的,字典“age24”指24歲以下的{原始單杠個(gè)數(shù):分?jǐn)?shù)}字典,“age25_27”指25~27歲的{原始單杠個(gè)數(shù):分?jǐn)?shù)}字典。

下面代碼中有一些注釋掉的語句,是為了中間測(cè)試,并且有大部分已經(jīng)被刪除了,因?yàn)閷?shí)際編程過程中,都是每一小段代碼都要測(cè)試的,成功了才能繼續(xù)下步,就像大樓一層一層的建起來。

# 男性單杠引體向上的成績(jī)計(jì)算,40歲及以上計(jì)算俯臥撐個(gè)數(shù)
# 從工作表“男子引體向上標(biāo)準(zhǔn)”中讀取數(shù)據(jù)
import openpyxl
class Pullup_standard_data():
    wb=openpyxl.load_workbook('通用訓(xùn)練課目考核成績(jī)計(jì)算.xlsx')
    ws_pullup = wb['男子引體向上標(biāo)準(zhǔn)']

    age24 = {}     # 24歲以下,{原始單杠個(gè)數(shù):分?jǐn)?shù)}
    age25_27 = {}  # 25~27歲,{原始單杠個(gè)數(shù):分?jǐn)?shù)}
    age28_30 = {}
    age31_33 = {}
    age34_36 = {}
    age37_39 = {}

    rngs1 = ws_pullup.iter_rows(min_row=3,max_row=23,min_col=1,max_col=9)
    # 生成{原始單杠個(gè)數(shù):分?jǐn)?shù)}的字典
    for row in rngs1:
        # print([c.value for c in row]) # 打印查看
        age24[row[1].value] = row[0].value  # row[0].value為分?jǐn)?shù),row[1].value為24歲以下單杠個(gè)數(shù)
        age25_27[row[2].value] = row[0].value
        age28_30[row[3].value] = row[0].value
        age31_33[row[4].value] = row[0].value
        age34_36[row[6].value] = row[5].value
        age37_39[row[8].value] = row[7].value
    # print('-----age24-----') # 打印數(shù)據(jù)以便檢查
    # for m in age24.items():
    #     print(m)
    # print('-----age25_27-----')
    # for m in age25_27.items():
    #     print(m)
    # print('-----age28_30-----')
    # for m in age28_30.items():
    #     print(m)
    # print('-----age31_33-----')
    # for m in age31_33.items():
    #     print(m)
    # print('-----age34_36-----')
    # for m in age34_36.items():
    #     print(m)
    # print('-----age37_39-----')
    # for m in age37_39.items():
    #     print(m)

    age40_42 = {}  # 40歲以上,{原始俯臥撐個(gè)數(shù):分?jǐn)?shù)}
    age43_45 = {}  # 43~45歲,{原始俯臥撐個(gè)數(shù):分?jǐn)?shù)}
    age46_48 = {}
    age49_51 = {}
    age52_54 = {}
    age55_57 = {}
    age58_59 = {}

    rngs2 = ws_pullup.iter_rows(min_row=29,max_row=78,min_col=1,max_col=13)
    # 生成{原始俯臥撐個(gè)數(shù):分?jǐn)?shù)}的字典
    for row in rngs2:
        # print([c.value for c in row])
        age40_42[row[1].value] = row[0].value  # row[0].value為俯臥撐分?jǐn)?shù),row[1].value為俯臥撐個(gè)數(shù)
        age43_45[row[3].value] = row[2].value
        age46_48[row[5].value] = row[4].value
        age49_51[row[6].value] = row[4].value
        age52_54[row[8].value] = row[7].value
        age55_57[row[10].value] = row[9].value
        age58_59[row[12].value] = row[11].value

    # print('-----age40_42-----') # 打印數(shù)據(jù)以便檢查
    # for m in age40_42.items():
    #     print(m)
    # print('-----age43_45-----')
    # for m in age43_45.items():
    #     print(m)
    # print('-----age46_48-----')
    # for m in age46_48.items():
    #     print(m)
    # print('-----age49_51-----')
    # for m in age49_51.items():
    #     print(m)
    # print('-----age52_54-----')
    # for m in age52_54.items():
    #     print(m)
    # print('-----age55_57-----')
    # for m in age55_57.items():
    #     print(m)
    # print('-----age58_59-----')
    # for m in age58_59.items():
    #     print(m)

2.設(shè)計(jì)計(jì)算函數(shù)pullup_performance_computing(),首先IF語句判定年齡;再判定是否小于55分的引體向上個(gè)數(shù),是則返回0分;再判定是否大于100分的引體向上個(gè)數(shù),是則按照引體向上超出100分,每遞增一次增加1分計(jì)算;最后55分~100分的情況,查詢字典,返回對(duì)應(yīng)分?jǐn)?shù)。對(duì)于一類人員65分及格、二類人員60分及格的情況,后期在主程序里考慮。

#函數(shù)的參數(shù),age是年齡,original_amount是原始引體向上的個(gè)數(shù)
    def pullup_performance_computing(self,age,original_amount):
        '''根據(jù)年齡,實(shí)際單杠個(gè)數(shù),計(jì)算所得分?jǐn)?shù)'''
        if age <= 24:  # 判定年齡
            if original_amount < 10:  # 判定是否小于55分的引體向上個(gè)數(shù),是則返回0分
                return 0
            elif original_amount > 30:  # 判定是否大于100分的引體向上個(gè)數(shù),是則按照引體向上超出100分計(jì)算
                return 100+original_amount-30
            elif 10 <= original_amount <= 30:  # 查詢字典,返回對(duì)應(yīng)分?jǐn)?shù)
                return self.age24[original_amount]
        elif 25 <= age <= 27:
            if original_amount < 9:
                return 0
            elif original_amount > 28:
                return 100+original_amount-28
            elif 9 <= original_amount <= 28:
                return self.age25_27[original_amount]
        elif 28 <= age <= 30:
            if original_amount < 8:
                return 0
            elif original_amount > 26:
                return 100+original_amount-26
            elif 8 <= original_amount <= 26:
                return self.age28_30[original_amount]
        elif 31 <= age <= 33:
            if original_amount < 7:
                return 0
            elif original_amount > 23:
                return 100+original_amount-23
            elif 7 <= original_amount <= 23:
                return self.age31_33[original_amount]
        elif 34 <= age <= 36:
            if original_amount < 6:
                return 0
            elif original_amount > 20:
                return 100+original_amount-20
            elif 6 <= original_amount <= 20:
                return self.age34_36[original_amount]
        elif 37 <= age <= 39:
            if original_amount < 5:
                return 0
            elif original_amount > 17:
                return 100+original_amount-17
            elif 5 <= original_amount <= 17:
                return self.age37_39[original_amount]

        # 計(jì)算俯臥撐
        elif 40 <= age <= 42:
            if original_amount < 27:
                return 0
            elif original_amount > 73:
                return 100 + (original_amount - 73) * 0.5
            elif 27 <= original_amount <= 73:
                return self.age40_42[original_amount]
        elif 43 <= age <= 45:
            if original_amount < 26:
                return 0
            elif original_amount > 69:
                return 100 + (original_amount - 69) * 0.5
            elif 26 <= original_amount <= 69:
                return self.age43_45[original_amount]
        elif 46 <= age <= 48:
            if original_amount < 23:
                return 0
            elif original_amount > 68:
                return 100 + (original_amount - 68) * 0.5
            elif 23 <= original_amount <= 68:
                return self.age46_48[original_amount]
        elif 49 <= age <= 51:
            if original_amount < 21:
                return 0
            elif original_amount > 66:
                return 100 + (original_amount - 66) * 0.5
            elif 21 <= original_amount <= 66:
                return self.age49_51[original_amount]
        elif 52 <= age <= 54:
            if original_amount < 18:
                return 0
            elif original_amount > 65:
                return 100 + (original_amount - 65) * 0.5
            elif 18 <= original_amount <= 65:
                return self.age52_54[original_amount]
        elif 55 <= age <= 57:
            if original_amount < 16:
                return 0
            elif original_amount > 62:
                return 100 + (original_amount - 62) * 0.5
            elif 16 <= original_amount <= 62:
                return self.age55_57[original_amount]
        elif 58 <= age <= 59:
            if original_amount < 10:
                return 0
            elif original_amount > 44:
                return 100 + (original_amount - 44) * 0.5
            elif 10 <= original_amount <= 44:
                return self.age58_59[original_amount]

3.測(cè)試模塊計(jì)算是否正確。

if __name__ == "__main__":
    pup_std_data = Pullup_standard_data()
    result = pup_std_data.pullup_performance_computing(49,68) # 修改這里的參數(shù)即可測(cè)試不同情況
    print(result)

4.對(duì)主程序training_performance.py進(jìn)行修改,如果引體向上的原始成績(jī)不為空,則進(jìn)行計(jì)算分?jǐn)?shù),再將分?jǐn)?shù)寫入表中引體向上的換算成績(jī)的位置。

import openpyxl
import datetime as dt
from pullup_standard_data import Pullup_standard_data

wb=openpyxl.load_workbook('通用訓(xùn)練課目考核成績(jī)計(jì)算.xlsx')
ws_training_performance = wb['體能考核成績(jī)']

pullup_sd = Pullup_standard_data()

def calculate_age(born):
    '''由出生日期計(jì)算年齡,精確到天'''
    today =dt.datetime.today()
    # today = today.replace(year=2020)
    # print(born)
    try:
        birthday = born.replace(year = today.year)
    except ValueError:
        # 出生日期是2月29日但若今年不是潤(rùn)年時(shí),29要減1天為28天
        birthday = born.replace(year=today.year, day=born.day-1)
    # print(birthday)
    if birthday > today:
        return today.year - born.year - 1
    else:
        return today.year - born.year

rngs = ws_training_performance.iter_rows(min_row=6,min_col=2)
for row in rngs:
    if row[3].value:
        # print(row[3].value)
        age = calculate_age(row[3].value)    # 由出生日期計(jì)算年齡,精確到天
        row[4].value = age
        if row[9].value:  #如果引體向上的原始成績(jī)不為空
            row[10].value = pullup_sd.pullup_performance_computing(row[4].value, row[9].value)
            print(row[9].value,row[10].value)

wb.save('計(jì)算結(jié)果.xlsx')

運(yùn)行后,生成文件“計(jì)算結(jié)果.xlsx”如下:


男子引體向上計(jì)算結(jié)果

到此,我們成功實(shí)現(xiàn)了男子引體向上計(jì)算的功能。

原創(chuàng)不易,有償下載,請(qǐng)多支持:
軍事體能考核成績(jī)?cè)u(píng)定系統(tǒng)下載

軍事體能考核成績(jī)?cè)u(píng)定系統(tǒng)全套Python源碼下載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容