PY-pandas | 作业-体测成绩转换

#%%
# CY3761 | 2022-01-08 15:33
#%%
# 此为 jupyter 模版, 执行 build 后记住先执行-全部运行
# 使用 DataSpell 进行编写文档
# 变量名、函数名小写分段处理
#%%
# 导入项
import numpy as np
import pandas as pd

np.array((np, pd))
#%%
def print_data(o):
    o_items = dict(dtype=None,dtypes=None,shape=None,size=None,index=None,columns=None)

    for (k,v) in o_items.items():
        try:
            o_items[k] = eval(f'o.{k}')
        except (Exception, BaseException):
            pass

    print(type(o), '\n', o_items)

def get_new_file_path(file_path, string, file_ext=None):
    file_sep = '.'
    file_path_split = file_path.split(file_sep)

    if not file_ext:
        file_ext = file_path_split.pop()  # 获取最后一个

    return file_sep.join(file_path_split) + '-' + string + file_sep + file_ext
#%%
r_rang = 26
r_chr = {k: [chr(_) for _ in range(size, size+r_rang)] for k,size in dict(b=65, s=97).items()}  # 大写字母索引 小写字母索引
pd.DataFrame(r_chr, index=range(1, r_rang+1))  # 字母表 b: 大写 s: 小写
#%% md
# 作业-体测成绩转换
#%% md
+ 知识点概述
+ 数据转换
+ 体侧成绩评分表数据转换
+ 男生体侧成绩分数转换
+ 女生体侧成绩分数转换
+ 保存成绩
#%% md
## 知识点概述
#%% md
### 字符串替换
#%%
a01 = '我大学体能极限是1000米3分34秒'
a01.replace('我', '派')  # 将字符串中的 "我" 替换成 "派" | 在字符串中找到第一个参数值并替换为第二参数值
#%%
a02 = "4'04"
float(a02.replace("'", '.'))  # 字符串替换为浮点数 这里需要注意, 转换后的字符串如果是能转为数值那可以这样 否则报错
#%%
print('"', "'")  # 字符串内容: 仅单引号(使用双引号扩住) 仅双引号(使用单引号扩住)
print('"\'', "\"'", '\'"', "'\"")  # 字符串内容: 单引号+双引号 (字符串内的引号与扩住的引号相同, 需要反斜线进行转义)
print(''''"''', """"'""")  # 使用三引号扩住: 无需转义处理, 扩住的引号 与 内容引号 不能作为 末尾字符
print('\\', "\\", '''\_''', """\_""")  # 反斜杠: 需要将其进行转义(作末尾字符) 或 使用三引号扩住: 但不能作为末尾字符
print(r'\_', '\_', r"\_", '\_')  # 反斜杠可以不进行转义 但不能作为末尾字符 | 主要原因是反斜杠会与后面的字符作为一个整体
#%% md
### 报错演示与修复
#%%
a03 = ["4'03", "4'34", "4'29", "3'48", "3'58", 4]
# [_.replace("'",'.') for _ in a03]  # 循环时可能参数的数据类型是不定的如果非字符串 就不能直接替换了 | AttributeError: 'int' object has no attribute 'replace'

b03 = [(
    float(str(_).replace("'",'.')),
    float(_.replace("'",'.')) if isinstance(_, str) else _  # 或者这样
    ) for _ in a03] # 这就正常了 并且转为浮点型

np.array(b03)
#%%
# 读取文件后 没有代码提示
path_01 = '体测成绩.xlsx'  # 有男生女生 2张表
# 男: m(Male) 女: f(Female)
xls_01_m = pd.read_excel(path_01, sheet_name='男生')
xls_01_f = pd.read_excel(path_01, sheet_name='女生')

print(xls_01_m.shape, xls_01_f.shape)

# 仅显示 头10条数据
head = 5
display(xls_01_m.head(head))
xls_01_f.head(head)
#%% md
## 数据转换
#%% md
+ 里面有空数据,说明这名学生没有参加这项体侧,将空数据填充为0
+ 1000米跑的数据需要转换,将4'13(字符串)转为 4.13(浮点数)
#%%
xls_01_m = xls_01_m.fillna(0)  # 填充空数据的会替换为0
xls_01_f = xls_01_f.fillna(0)  # 填充空数据的会替换为0
display(xls_01_m.head(head))
xls_01_f.head(head)
#%%
def func01(x):
    return float(str(x).replace("'", '.'))

xls_01_m['男1000米跑'] = xls_01_m['男1000米跑'].map(func01)
xls_01_f['女800米跑'] = xls_01_f['女800米跑'].map(func01)

pd.DataFrame(dict(1000米跑=xls_01_m['男1000米跑'],800米跑=xls_01_f['女800米跑'])).head(head)
#%%
# 文件保存

# 一起保存
with pd.ExcelWriter(get_new_file_path(path_01, '男女生结果1')) as w:
    xls_01_m.to_excel(w,  sheet_name='男生', index=False)
    xls_01_f.to_excel(w,  sheet_name='女生', index=False)

# 分开保存
xls_01_m.to_excel(get_new_file_path(path_01, '男生结果1'),  sheet_name='男生', index=False)
xls_01_f.to_excel(get_new_file_path(path_01, '女生结果1'),  sheet_name='女生', index=False)
#%% md
## 体侧成绩评分表数据转换

#%%
path_02 = '体侧成绩评分表.xls'  # 表头2行 多层索引
xls_02 = pd.read_excel(path_02, header=[0,1])
xls_02 = xls_02.fillna(0)  # 数据清洗

print(xls_02.shape)
xls_02.head(head)
#%%
def func02(x):
    """
        m,s = [int(_) for _ in str(x).strip('"').split("'")]  # 去除尾部引号 使用 单引号进行分割 使用列表生产式进行处理值

        return m + s/100  # 结果返回 成绩 s是 0~99 100个数
    """
    return float(str(x).replace('"', '').replace("'", '.'))  # 也可以直接这样返回
#%%
# 男1000米跑 成绩
# xls_02['男1000米跑']['成绩'] # 可以通过此获取数据
# xls_02.iloc[:,-4] # 先行后列 列获取所有行 : , 列获取倒数第4列 (末尾列是-1) | 列索引按照最原始计算方式(没有合并) | 写入需要使用这个

# 女800米跑 成绩
# xls_02['女800米跑']['成绩']  # 可以通过此获取数据
# xls_02.iloc[:,-2]  # 写入需要使用这个

pd.DataFrame(dict(1000米跑成绩=xls_02['男1000米跑']['成绩'],800米跑成绩=xls_02['女800米跑']['成绩']))
#%%
# 这里不用关键字索引 多个中括号 因为第二个中括号视为行号
xls_02.iloc[:,-4] = xls_02.iloc[:,-4].apply(func02)
xls_02.iloc[:,-2] = xls_02.iloc[:,-2].apply(func02)

pd.DataFrame(dict(1000米跑成绩=xls_02['男1000米跑']['成绩'],800米跑成绩=xls_02['女800米跑']['成绩']))
#%%
# 数据保存
xls_02.to_excel(get_new_file_path(path_02, '结果1', 'xlsx'))  # 如果安装原格式保存 xls 会出现提示信息 | 多层索引不能设置index 头信息是默认True | 可修改后缀
#%%
# 保存数据进行读取加载 注意加载后效果第一行数据是全0
xls_03 = pd.read_excel(get_new_file_path(path_02, '结果1', 'xlsx'), header=[0,1], index_col=0) # 这里需要设置 index_col 第一列索引0作为行索引(该列有值才开始算)
print(xls_03.shape)
xls_03.head(head)
#%% md
+ 通过2个文件进行分析,将成绩分数进行转换
+ 一个是 path_01 经过数据清洗后的文件
+ 一个是 path_02 具有成绩分数的的文件
+ 通过 path_02 进行分析 给 path_01 进行计算
+ path_02 为评分标准界限
#%% md
## 男生体侧成绩分数转换 与 女生体侧成绩分数转换
#%%
%%time

def func03(x, k):  # 男生+女生
    if x == 0: # 没有进行体能测试 分数0
        return 0

    y = xls_03[k]

    for _ in range(xls_03.shape[0]):
        if x <= y['成绩'][_]:  # 速度型 比小 | 值越小分数越高
            return y['分数'][_]

    return 0  # 数值少于界限内分数

def func04(x, k):  # 男生+女生
    if x == 0: # 没有进行体能测试 分数0
        return 0

    y = xls_03[k]

    for _ in range(xls_03.shape[0]):
        if x >= y['成绩'][_]:  # 力量型 比大 | 值越大分数越高
            return y['分数'][_]

    return 0  # 数值少于界限内分数

forString = '-分数'

insert_items = [[list(xls_01_m.columns)[_], list(xls_01_f.columns)[_]] for _ in range(2, xls_01_m.shape[1])]

# 增加第三个参数注入
# 看评分表的数据情况 成绩与分数 如果 成绩越大分数越大 就大于 力量型 | 如果成绩越小分数越大 就小于 速度型
# 男1000米跑/女800米跑 | 速度型
# 男50米跑/女50米跑 | 速度型
# 男跳远/女跳远 | 力量型
# 男体前屈/女体前屈 | 力量型
# 男引体/女仰卧 | 力量型
# 男肺活量/女肺活量 | 力量型

func_items = [None] * len(insert_items)
func_items = [func03, func03, func04, func04, func04, func04] + func_items

for k,_ in enumerate(insert_items):
    insert_items[k].append(func_items[k])

for (m,f, func) in insert_items:
    if not func:
        continue

    xls_01_m.insert(list(xls_01_m.columns).index(m) + 1, m + forString, xls_01_m[m].apply(func, args=(m,)))
    xls_01_f.insert(list(xls_01_f.columns).index(f) + 1, f + forString, xls_01_f[f].apply(func, args=(f,)))

display(xls_01_m.head(head))
xls_01_f.head(head)
#%% md
##
#%% md
## 保存成绩
#%%
with pd.ExcelWriter(get_new_file_path(path_01,'男女生结果2')) as w:
    xls_01_m.to_excel(w, sheet_name='男生', index=False)
    xls_01_f.to_excel(w, sheet_name='女生', index=False)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CY3761

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

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

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

打赏作者

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

抵扣说明:

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

余额充值