基于Numpy和python面向对象浅尝试——成绩单的运算

最近在学python面向对象 正好也在学数据分析与可视化

正好就拿题目来练练手

如题

这是附件内的数据

题目要求是输出对应的几个值 出于挑战,这里想要写一个类来完成对这类成绩单的处理,让其对其他的类似成绩单也有作用

所以程序的可用性有一定要求

举例来说

比如说这个文件第二列是没有用的 需要跳过,但是别的文件可能不需要跳过 或者需要跳过更多列数,所以在处理这个问题的时候就需要考虑到到底需要跳过多少列

我在代码中要求输入了需要跳过的列数来达到这个目的

当然还有很多和上面一样需要考虑的地方

# 用于读取csv文件内的成绩单 运算结果后返回
# 支持多种运算 
# 本来准备自己写运算的 但是毕竟别人都写好了 不用白不用
# author = WHUT_L1_Sta2
# 希望以后能够设计一个UI出来
# ver = 1.0

import numpy as np
    
class scores:
    '''
    类内部需要实现的方法
    1 读取 多行多列的成绩表(csv)
    2 检索 找到关键词对应的行或列(这点在np里面不好实现) 
    3 计算 计算多种值 为了方便直接调用np的库算了  
    4 输出 任意类中的数值
    '''

 首先是开头,定义一个类

出于个人习惯 我把要在类内部实现的方法写在了类下方的注释里

先来实现前几个功能 


    def __init__(self, lines: int, rows: int) -> None:
        '''
        简单获取三个值以初始化
        行数 列数 路径
        '''
        self.name = input('请输入需要计算成绩的人名')
        self.subject = input('请输入需要计算成绩数据的科目')
        self.lines = lines
        self.rows = rows
        # 这俩也可以用input() 相应的 就不要初始化参数了
        # 这里这样写是因为想要两种方法都试一下

    def my_read(self, csv_name) -> None:
        '''
        传入文件名以开始
        暂时不提供间隔选项,会在之后看需求更新
        默认逗号和回车'''
        with open(csv_name, encoding='utf-8') as f:
            self.data = f.read().replace('\n', ',').split(',')

    def my_find(self) -> None:
        '''
        查找人名和科目所对应的行列数
        在转化为二维数组之后很难实现
        我把它放到了自带的读取文件后
        并且把它放在转换二维数组之前
        '''
        self.need_line = self.data.index(self.subject)
        self.need_row = self.data.index(self.name) // (self.lines - 1)
        # 这里计算出是第几行 因为上面得到的是一个一维的列表

    def my_array(self) -> None:
        '''转化为二维数组'''
        self.array = np.array(self.data).reshape(self.rows, self.lines)
        # 根据输入的行列数转换为二维数组

类里面的第一个方法是初始化,在这里我要求输入文件的行数,列数和文件路径并且对参数完成了赋值,用self可以完成参数在类内部不同方法里的传递。值得一提的是本来可以直接计算出文件的行列数,但是我没那样做,因为那样需要先转换为二维数组,但是那样就不太好实现对列表行列名的查找,所以这里要求直接输入

类里面的第二个方法是读文件 这里直接用系统的来读,将所有回车换为逗号后用逗号分隔

类里面的第三个方法是查找 用于检索列名或者行名所对应的列或者行的索引数,这里如果先转为二维数组就难以进行索引了

类里面的第四个方法是转数组,这里直接用np里面的方法来转数组 写到这里我突然就在想 为什么我不自己写 还要调用np里面的方法,我明明拥有行列数了,那么我可以直接对数据操作来得到一个二维数组。 归根到底还是我太懒了,下次一定不导入别人的库,争取自己完完整整的写

    def my_skip(self, skip_lines=0, skip_rows = 0) -> None:
        '''
        通常用于第二列不为成绩的情况
        默认不跳
        '''
        self.skip_lines = skip_lines

 类里面的第五个方法是跳列 写这个的时候我也犹豫了下,因为本身read()方法里面是可以直接设置跳行跳列的,但是那样的话后面就不太好完成查找方法了,因为我想尽量保证数组的完整性,所以每次都是直接对原始数组进行操作,原始的数组没有保存,无法用原始数组进行查找,但是这样可以避免在数据过多的时候占用过多的储存空间


    def my_total(self) -> str:
        '''计算某同学的总分方法'''
        self.total = sum(
            self.array[self.need_row, self.skip_lines:].astype(int))
        # 成绩从第几列开始 就从第几列开始算
        return (f'{self.name}同学的总分为{self.total :.2f}')

    def my_ave(self) -> str:
        '''计算某同学的平均分'''
        self.ave = self.total / (self.lines - self.skip_lines)
        # 科目数计算为总行数减去跳过的行数
        return (f'{self.name}同学的平均分为{self.ave :.2f}')

    def sub_ave(self) -> str:
        '''求单科班级平均分'''
        ave_sub = np.mean(self.array[1:, self.need_line].astype(int))
        # 从需要的列的第一行开始
        return (f'{self.subject}课程平均成绩为{ave_sub:.2f}')

    def sub_medium(self) -> str:
        '''求单科班级中位数'''
        medium_sub = np.median(self.array[1:, self.need_line].astype(int))
        return (f'{self.subject}课程中位数为{medium_sub:.2f}')

    def sub_std(self) -> str:
        '''求单科班级标准差'''
        std_sub = np.std(self.array[1:, self.need_line].astype(int))
        return(f'{self.subject}课程标准差为{std_sub:.2f}')

 类里面的最后几个方法就没有太大的难度了,本来也打算自己写的,但是既然都调np库了就直接用吧,反正也不难

 最后测试

if __name__ == '__main__':
    lines = int(input('请输入文件列数'))
    rows = int(input('请输入文件行数'))
    csv_name = input('请将文件置于同一文件夹并输入文件名(不带引号)')  # 这里可以改成input
    sc = scores(lines, rows)  # 创建实例对象
    sc.my_read(csv_name)
    sc.my_find()
    sc.my_array()
    sc.my_skip(int(input('请输入成绩从第几列开始(索引数)')), int(input('请输入成绩从第几行开始(索引数)')))
    print(sc.my_total())
    print(sc.my_ave())
    print(sc.sub_ave())
    print(sc.sub_medium())
    print(sc.sub_std())

最后输入一大堆的结果

 最后如果要完成上面题目的话 记得要删除掉input()当中的字符和部分input()并对没有给出的参数进行提前赋值

总结: 手贱,再也不写类了,老老实实的面向过程吧

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值