#%%
# 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)
PY-pandas | 作业-体测成绩转换
最新推荐文章于 2023-05-21 11:19:32 发布