使用类计算python的平均值

2024-04-16 16:58:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用python从一系列空气质量监测仪中读取数据。在

目前我正在做下面的计算平均数。我想肯定有更好的方法来使用类来实现这一点,因为大多数代码都会重复自身,这样才能使它更普遍地适用于更高效地工作。在

另一个问题是我有许多不同类型的监视器,它们基本上是按照相同的原理工作,但变量略有不同。下面给出的代码是一个真正的噩梦移动到一个新的监视器,因为我必须编辑每一行。在

麻烦的是,当我搜索班级和平均数时,我得到的似乎只是平均学生在学校一个班级的成绩,而不是用一个软件类从多个变量计算平均值。在

基本上,显示器每秒只读取一个读数,但我只需要1分钟的平均值,所以我反复地跟踪,直到分钟结束。在

如有任何建议,不胜感激。在

目前我正在做这个:

while minute unchanged:
    ## read serial port

    readData = SER.read()  

    ## Split comma delimited data into dust, flow, temperature, relative humidity, pressure
    ## for example data comes in as 000.007,2.0,+21.7,046,1010.0
    measData = readData[0].split(',')           
    dustReading = measData[0].strip()                       

    flowReading = measData[1]
    flowReading = flowReading.strip()

    tempReading = measData[2]
    tempReading = tempReading.strip()

    rhReading = measData[3]
    rhReading = rhReading.strip()

    pressReading = measData[4]
    pressReading = pressReading.strip()


    ######### Dust #######

    try :   
        nReading = nReading+1   
        dustReading = float(dustReading)
        sumDustReading = sumDustReading + dustReading
        meanDustReading = sumReading/float(nReading)            
    except :
         pass       

    ####### Flow ##########
    try :   
        flowReading = float(flowReading)
        sumFlowReading = sumFlowReading+flowReading
        meanFlowReading = float(sumFlowReading)/float(nReading)
    except :
         pass                       

    ######## Temperature #########
    try:    
        tempReading = float(tempReading)
        sumTempReading = sumTempReading+tempReading
        meanTempReading = float(sumTempReading)/float(nReading)
    except :
         pass

    ######### RH ########
    try :   
        rhReading = float(rhReading)
        sumRhReading = sumRhReading+rhReading
        meanRhReading = float(sumRhReading)/float(nReading)
    except :
         pass       

    ###### Pressure Reading ######
    try :   
        pressReading = float(pressReading)
        sumPressReading = sumPressReading+pressReading
        meanPressReading = float(sumPressReading)/float(nReading)               
    except :
        pass

理想情况下,我希望能够得到

^{2}$

万分感谢。在


Tags: passfloatstriptryexceptpressreadingflowreadingsumtempreading
2条回答

对于所有这些try:...except块,您现有的代码有点奇怪,而且很危险。这很危险,因为它忽略了所有应该而不是的错误。例如:试图使用未定义变量的值、被零除错误和完全语法错误。在


你可以用类做你想做的事情,但是对于这样的事情,我更倾向于使用一个简单的dict。我将发布这两种方法的代码,以帮助您做出决定(或增加您的困惑:)。在

显然,我没有你的监控硬件连接到我的串行端口,所以为了测试这段代码,我写了一个简单的生成器函数,它创建了随机的假数据。希望您可以很容易地修改我的代码。在

首先,使用一个类的代码,该类保存当前的总数和读取数;这个类还有一个属性,可以按需计算平均值。所以如果你愿意,你可以做print dust.total, flow.mean之类的事情。在

from random import seed, random

#A generator to make simulated data
def fake_data(n):
    for i in range(n):
        d = 0.005 + 0.005 * random()
        f = 1.5 + random()
        t = 20.0 + 5.0 * random()
        h = int(40 + 10.0 * random())
        p = 1005.0 + 10.0 * random()

        s = '%07.3f,%3.1f,%-4.1f,%03d,%6.1f' % (d, f, t, h, p)
        yield [s]


class Data(object):
    def __init__(self, name):
        self.name = name
        self.total = 0
        self.numberOfReads = 0

    def __repr__(self):
        fmt = "Data(name='%s', total=%f, number=%d, mean=%f)"
        return fmt % (self.name, self.total, self.numberOfReads, self.mean)

    def __str__(self):
        fmt = '%s\nmean: %f\nnumber: %d\ntotal: %f\n'
        return fmt % (self.name, self.mean, self.numberOfReads, self.total)

    def add(self, value):
        self.total += value
        self.numberOfReads += 1

    @property
    def mean(self):
        try:
            return float(self.total) / float(self.numberOfReads)
        except ZeroDivisionError:
            return None


#Seed the randomiser
seed(1)

#Initialise the Data instances
dust = Data('Dust')
flow = Data('Flow')
temp = Data('Temperature')
rh = Data('Relative Humidity')
press = Data('Pressure')

for readData in fake_data(10):
    ## Split comma delimited data into dust, flow, temperature, relative humidity, pressure
    ## for example data comes in as 000.007,2.0,+21.7,046,1010.0
    print readData
    measData = readData[0].split(',')

    #Convert data strings to floats
    dustR, flowR, tempR, rhR, pressR = [float(s) for s in measData]

    #Add new data to current totals
    dust.add(dustR)
    flow.add(flowR)
    temp.add(tempR)
    rh.add(rhR)
    press.add(pressR)

print

for a in (dust, flow, temp, rh, press):
    print a

输出

^{pr2}$

下面是使用dict的版本。我已经将随机化器种子设置为相同的值,这样假数据与前一个版本相同。在

from random import seed, random

#A generator to make simulated data
def fake_data(n):
    for i in range(n):
        d = 0.005 + 0.005 * random()
        f = 1.5 + random()
        t = 20.0 + 5.0 * random()
        h = int(40 + 10.0 * random())
        p = 1005.0 + 10.0 * random()

        s = '%07.3f,%3.1f,%-4.1f,%03d,%6.1f' % (d, f, t, h, p)
        yield [s]


#Seed the randomiser
seed(1)

#data field names
fields = ('Dust', 'Flow', 'Temp', 'rh', 'press')

#initialise the data dictionary 
data = dict.fromkeys(fields, 0.0)

nReading = 0
for readData in fake_data(10):
    nReading += 1

    ## Split comma delimited data into dust, flow, temperature, relative humidity, pressure
    ## for example data comes in as 000.007,2.0,+21.7,046,1010.0
    print nReading, readData
    measData = readData[0].split(',')

    #Convert data strings to floats
    floatData = [float(s) for s in measData]

    #Add new data to current totals
    for key, value in zip(fields, floatData):
        data[key] += value

print '\nNumber of readings = %d\n' % nReading
nReading = float(nReading)
for key in fields:
    total = data[key]
    mean = total / nReading
    print '%s\nmean: %f\ntotal: %f\n' % (key, mean, total)

输出

1 ['000.006,2.3,23.8,042,1010.0']
2 ['000.007,2.2,23.9,040,1005.3']
3 ['000.009,1.9,23.8,040,1009.5']
4 ['000.009,1.7,24.7,049,1005.3']
5 ['000.005,2.0,24.7,043,1007.2']
6 ['000.007,1.5,21.1,044,1010.0']
7 ['000.006,1.7,21.1,044,1007.9']
8 ['000.005,2.3,22.8,046,1006.9']
9 ['000.010,2.4,20.6,043,1012.2']
10 ['000.009,2.4,22.1,048,1011.7']

Number of readings = 10

Dust
mean: 0.007300
total: 0.073000

Flow
mean: 2.040000
total: 20.400000

Temp
mean: 22.860000
total: 228.600000

rh
mean: 43.900000
total: 439.000000

press
mean: 1008.600000
total: 10086.000000

下面是一个使用try:... except验证输入数据的简单示例。在

data = [
    '1.1 2.2 3.3',
    '4 5',
    '6 garbage bytes',
    '7 8 9 10',
    '11 12 13',
]

for i, line in enumerate(data):
    print '\nLine %d: %r' % (i, line)
    row = line.split()
    if len(row) != 3:
        print 'Bad row length. Should be 3 not', len(row)
        continue

    try:
        a, b, c = [float(s) for s in row]
    except ValueError as err:
        print 'Conversion error:', err
        continue

    print 'Data %d: a=%f, b=%f, c=%f' % (i, a, b, c)

输出

Line 0: '1.1 2.2 3.3'
Data 0: a=1.100000, b=2.200000, c=3.300000

Line 1: '4 5'
Bad row length. Should be 3 not 2

Line 2: '6 garbage bytes'
Conversion error: invalid literal for float(): garbage

Line 3: '7 8 9 10'
Bad row length. Should be 3 not 4

Line 4: '11 12 13'
Data 4: a=11.000000, b=12.000000, c=13.000000

如果将数据保存在列表中,则更容易计算平均值和其他统计属性。列表的长度和总和都是内置的。在

所以首先列出一些清单。在

dust, flow, temp, rh, pressure = [], [], [], [], []

我将以以下数据为例。在

^{pr2}$

让我们把它分开

newdust, newflow, newtemp, newrh, newpressure = [float(n) for n in readData.split(',')]
dust.append(newdust)
...
pressure.append(newpressure)

要计算平均值:

sum(pressure)/len(pressure)

更新

在没有看到不同类型仪器生成的数据的情况下,很难给出处理不同类型仪器的建议。在

例如,您可以为每种不同类型的传感器编写一个数据转换函数,该函数从串行端口读取一条线,并返回一个tuple或{}的数据,其测量值不受特定设备的支持,如None。 假设你知道你连接的是哪个传感器,然后在程序开始时选择正确的函数来调用

from collections import namedtuple

Instrumentrecord = namedtuple('Instrumentrecord',
                              ['dust', 'flow', 'temp', 'humidity', 
                               'pressure', 'windspeed', 'winddir'])

def foo_sensor(dataline):
    dust, flow, temp, rh, pressure = [float(n) for n in dataline.split(',')]
    return Instrumentrecord(dust, flow, temp, rh, pressure, None, None)


def main(argv):
    ....
    if sensortype == 'foo':
        current_sensor = foo_sensor
    ...
    data = []
    while keep_going:
        line = SER.read()
        data.append(current_sensor(line))

相关问题 更多 >