【问题标题】:score calculator with python and pandas带有 python 和 pandas 的分数计算器
【发布时间】:2020-09-28 10:41:41
【问题描述】:

我正在尝试制作一个简单的应用程序,以通过以下公式获取任何人在测试中的分数:

score=(平均成绩)/方差 例如,如果您的 20 分是 18 分,班级的平均分是 15 分,那么这个公式可以帮助您了解与其他人相比您的成绩如何。 我的代码打开一个位于我的电脑中的 excel 文件,读取点列将它们写入列表,然后获取平均值和方差并使用公式。 this is my excel file。 顺便说一句,excel中的成绩仅用于测试。 我已经尝试过这些代码(我不是使用类的专业人士,我试图利用它): 这是第一个

class taraz:
  def __init__(self,file_name,file_dir,your_point):
      self.file_name=file_name
      self.file_dir=file_dir
      self.your_point=your_point
  def sum_ave():
      f=pandas.read_excel(r (file_dir))
      point_list=f['point'].tolist()
      sum1=sum(point_list)
      ave1=sum1/len(point_list)
  def variance():
      for i in point_list:
        var1=sqrt(((i-ave1)**2)/len(point_list))
  def taraz1():
      taraz1=(your_point-ave1)/var1
      print(taraz1)
  print(taraz1)

这是第二个:

def taraz(file_name,file_dir,your_point):
  def sum_ave():
      f=pandas.read_excel(r (file_dir))
      point_list=f['point'].tolist()
      sum1=sum(point_list)
      ave1=sum1/len(point_list)
  def variance():
      for i in point_list:
          var1=sqrt(((i-ave1)**2)/len(point_list))
  def taraz1():
      taraz1=(your_point-ave1)/var1
      print(taraz1) 

从我刚得到的第一个代码并输出如下: ma​​in.taraz 对象位于 0x02528130> 从第二个开始,我根本没有得到输出。 无论如何,我很乐意使用您的提示。

【问题讨论】:

  • 你没有理解每个变量的作用域。
  • 比如第一个例子,sum_ave方法里面的file_dir是什么?您希望它如何理解该变量?
  • 另外,当你可以使用df.mean()df.var() 时,为什么要使用pandas 从excel 中读取数据,然后将该数据框转换为列表,然后定义自己的均值和方差函数?跨度>
  • 非常感谢,我不知道如果没有全局变量,我不能在函数外部使用变量。但我不熟悉 'df.mean' 和 'df.var' 请您进一步解释一下。
  • df 是用于数据帧的常用变量名称,它是 pandas 使用的变量类型。我在下面的回答展示了如何直接使用这两种方法,而不是重新实现它们。

标签: python excel pandas class oop


【解决方案1】:

首先,了解变量的作用域。如果一个变量是在一个方法中声明的,它只能从该方法中访问,除非它被声明为全局变量。

当涉及到您的代码时,您的类中的方差方法。

def variance():
    for i in point_list:
        var1=sqrt(((i-ave1)**2)/len(point_list))

variance 方法将如何理解 point_lits 变量。它既没有定义也没有声明为全局/类变量。

第二,类的方法将采用通常定义为self的默认参数,除非它被修饰为类方法。 check here了解self关键字。

第三,类将有对象但函数不会。所以你无法看到函数绑定的对象。

所以,添加 self 关键字后的代码将如下所示

from os import path


class Taraz:
    def __init__(self, file_name, file_dir, your_point):
        self.file_name = file_name
        self.file_dir = file_dir
        self.your_point = your_point
        self.point_list = None
        self.ave1 = None

    def sum_ave(self):
        f = pandas.read_excel(path.join(self.file_dir, self.file_name))
        self.point_list = f['point'].tolist()
        sum1 = sum(self.point_list)
        self.ave1 = sum1 / len(self.point_list)

    def variance(self):
        if self.point_list is not None and self.ave1 is not None:
            for i in self.point_list:
                var1 = sqrt(((i-self.ave1)**2) / len(self.point_list))

    def taraz1(self):
        taraz1 = (self.your_point - self.ave1) / var1
        print(taraz1)

编辑:

>>> def func():
...     pass
...
>>> class cla:
...     pass
...
>>> func()
>>> 
>>> cla()
<__main__.cla object at 0x0000019A55944550>
>>> func
<function func at 0x0000019A552D2EA0>
>>> cla
<class '__main__.cla'>

() 用于调用方法或函数。这里func 是一个函数,cla 是一个类。当您调用一个类时,它将返回该类的对象,因此您会在 0x0000019A55944550> 处看到 ma​​in.cla 对象,但是当您调用函数时,它将返回函数的响应。由于我的函数在这里没有任何内容,因此它没有重新调整任何内容。

【讨论】:

  • os.path.join(self.file_dir, self.file_name) 会更好。
  • 我进行了编辑以添加样式(类以大写开头,等号两边的空格,...),但不想在未经您批准的情况下更改实际代码中的任何内容。现在编辑为使用 os.path.join 而不是分隔符。
  • 非常感谢@LMKR 我完全理解您的前两个反对意见,但第三个反对意见对我来说仍然不清晰。如果可能的话,请给我进一步的解释。
  • 我认为他的意思是,在您的第二个示例中,您是在函数而不是类中定义函数。这实际上并不是一个错误,函数可以在任何地方声明,但是对于这个用例来说,在 other 内部声明一个函数是没有意义的,因为它只能从函数内部调用。
  • @LMKR 它们被称为实例。对类的调用将返回类类型的实例(除非您搞砸了元类和一些可能改变这种行为的更高级的特性)。对象是一个很笼统的名词,连函数本身也是对象。
【解决方案2】:

没有理由使用pandas从excel文件中读取,然后转换成列表,重新实现均值、方差等基本向量运算。

from os import path

import pandas as pd


class Taraz:
    def __init__(self, filepath):
        scores = pd.read_excel(filepath)['point']
        self.mean = scores.mean()
        self.var = scores.var()

    def score(self, score):
        return (score - self.mean) / self.var


if __name__ == '__main__':
    taraz = Taraz(path.join('path', 'to', 'the', 'file.xlsx'))
    print(taraz.score(16))

输出:

-0.012571428571428395

在您的示例中,您有几个我想评论的错误。

  1. 变量范围很重要。如果您在函数内部分配变量,它将在该函数内部分配。在它之外会引发 NameError。
  2. 方法的第一个参数(应该称为self,除了一些特殊方法)是实例本身,我们可以在其中分配将存储在实例中的值,然后再检索它们。例如,在上面代码的构造函数 (__init__) 方法中,我们为 self.mean 分配了一些值,该值将存储在实例中,以便我们以后可以在 score 方法中使用它。李>
  3. OOP(面向对象编程)是一种非常完善的编码模式,但试图强制将类用于不真正代表类型的东西似乎有点不必要。这可以在单个函数中轻松实现:
from os import path

import pandas as pd


def taraz(filepath):
    scores = pd.read_excel(filepath)
    mean = scores['point'].mean()
    var = scores['point'].var()
    scores['scores'] = (scores['point'] - mean) / var
    return scores


if __name__ == '__main__':
    print(taraz(path.join('path', 'to', 'the', 'file.xlsx')))

输出:

     name  point    scores
0    tghi     15 -0.163429
1    nghi     16 -0.012571
2   asghr     15 -0.163429
3    sbhn     20  0.590857
4    tghi     12 -0.616000
5    nghi     20  0.590857
6   asghr     17  0.138286
7    sbhn     18  0.289143
8    tghi     17  0.138286
9    nghi     16 -0.012571
10  asghr     15 -0.163429
11            12 -0.616000

如您所见,pandas 数据帧实现了向量运算,因此(scores['point'] - mean) / var 被转换为整数向量减去浮点数,再除以浮点数,该操作的结果是浮点向量,我们将其存储在“分数”列。这样我们计算每一行的分数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    • 1970-01-01
    • 2020-11-30
    • 2017-05-17
    • 2014-07-29
    相关资源
    最近更新 更多