【问题标题】:Calculate 20 minute average & best 20 minute average计算 20 分钟平均值和最佳 20 分钟平均值
【发布时间】:2020-04-25 06:56:33
【问题描述】:

我正在尝试学习 Python,我正在通过一个项目从自行车功率计读取数据。现在我只是在计算从开始到结束的平均功率,方法是将每个功率读数添加到总和变量中,然后除以读数的数量。

我想计算 20 分钟的平均功率,如果可能,在前 20 分钟后每 30 秒继续计算 20 分钟的平均值,与之前的值进行比较,如果高于上一个值,则将其存储,所以最后我可以拥有比一小时锻炼更高的 20 分钟平均力量,例如,无论那一小时发生在哪里。

功率计的数据是基于事件的,据我所知,这不是定期间隔,而是每秒一次或更快。 到目前为止,这是我的代码的基础:

def average_power(power, count):
    global PM1_sumwatt
    global PM1_avgwatt
    PM1_sumwatt = PM1_sumwatt + power
    PM1_avgwatt = PM1_sumwatt / count
    PM1_avgLog = open(PM1_avgFile, 'w')
    PM1_avgLog.write("<div id=\"pwr\"> %d W</div>" % (PM1_avgwatt))
    PM1_avgLog.close()

def power_data(eventCount, pedalDiff, pedalPowerRatio, cadence, accumPower, instantPower):
     global PM1_avgcount
     if WCORRECT1: calibpower = instantPower+(CF1w)
     else: calibpower = instantPower*(CF1x)
     power_meter.update(int(calibpower))
     PM1_avgcount = PM1_avgcount + 1
     average_power(int(calibpower), PM1_avgcount)


power  = BicyclePower(readnode, network, callbacks = {'onDevicePaired': device_found,
                                              'onPowerData': power_data})


# Starting PM readings
power.open(ChannelID(PM1, 11, 0))

不太清楚如何解决这个问题!非常感谢任何帮助或指针!

【问题讨论】:

  • 输入数据是什么?你能给我们看一段你的代码吗?
  • 欢迎堆栈溢出!不幸的是,这不是一个代码编写或教程网站,我们要求您为您的问题提供minimal reproducible example,包括示例输入、示例输出以及您根据自己的研究迄今为止尝试过的代码跨度>
  • 将功率读数保存在一个列表中。如果您每 30 秒阅读一次,那么列表中的最后 40 项将是最近 20 分钟的值。
  • 我刚刚添加了我正在使用的主要代码。第一个函数是整体平均计算,由第二个函数调用。在 BicyclePower 对象的每个事件上调用第二个函数。

标签: python average


【解决方案1】:

如果您是实时读取数据,我假设您是在 while 循环中读取数据:

sum = 0
number_of_readings = 0
while True:  # forever
    new_value = input()  # here I read from the console input
    sum += new_value
    number_of_readings += 1
    average = sum/number_of_readings 
    print(average)

在这里,我在控制台中输入一个数字,然后按 Enter 键来模拟您的自行车功率计。

>>> 1
1.0
>>> 3
2.0
>>> 4
2.6666666666666665
>>> 2
2.5

现在,如果您想制作移动平均线,则必须存储要平均的读数。这是因为您想稍后删除它们,当它们太旧时。 list 非常适合:

这是一个平均最后一次n 读数的解决方案:

n = 2
Last_n_readings = []
while True:  # forever
    # add a new reading
    new_value = int(input())  # here I read from the console input
    Last_n_readings.append(new_value)
    # discard an old one (except when we do not have enough readings yet)
    if len(Last_n_readings) > n:
        Last_n_readings.pop(0)
    # print the average of all the readings still in the list
    print(sum(Last_n_readings) / len(Last_n_readings))

这给出了:

>>> 1
1.0
>>> 3
2.0
>>> 4
3.5
>>> 2
3.0

请注意,列表在删除开始附近的元素时效率不高,因此有更有效的方法来做到这一点(循环缓冲区),但我尽量保持简单;)

您可以通过猜测您拥有多少读数/秒并选择n 来使用此功能,这样您的平均时间超过 20 分钟。
如果你想真正平均所有不到 20 分钟前的结果,你不仅需要记录读数,还需要记录你变红的时间,这样你就可以删除超过 20 分钟的旧读数。如果这是您需要的,请告诉我,我将通过示例扩展我的答案。

【讨论】:

  • 谢谢!功率计的读数是基于事件的,我认为它们不会定期发生,但我可能会尝试编写一些示例代码来存储读数几分钟,看看我是否能得出平均读数每分钟。这样我就可以使用你的代码了!
  • 好的!我已经在我当前的主程序中实现了这个并且似乎正在工作。我收集了带时间戳的数据,估计每分钟有 44 个读数。从那里几乎可以按原样使用您的代码。又快又脏,但它有效。也可以让 pandas 解决方案正常工作,但更多的是用于锻炼后分析,而不是在主程序中实时运行!谢谢@Raphael!
  • 不客气,感谢您的更新,非常感谢 :)
【解决方案2】:

您可以使用 pandas 数据框来存储每个实例的功率输出。

考虑到您每 30 秒收到一个值,您可以将它们全部存储在数据框中。

然后使用python中的滚动函数计算40个数据点的移动平均值。

取滚动函数后得到的最大值,这将是你的最终结果。

请参阅此文档:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.rolling.html

【讨论】:

  • 谢谢,我去看看!我没有每 30 秒从功率计接收一次值,比这快得多。我说的是我想每 30 秒比较 20 分钟的平均值,并与之前的 20 分钟平均值进行比较,如果更高则存储。功率计的数据是基于事件的,所以我认为它不会定期出现。
  • 在这种情况下,您可以将事件转换为最近的 30 秒并插入数据帧。如果您在特定的 30 秒窗口中没有收到任何事件,请插入 NA。之后,您可以使用滚动功能。如果我不清楚或者您在实施时遇到问题,请告诉我。
  • 我已经设置了主程序以将数据输出到 csv 文件:第一列只有日期时间,第二列和第三列只有 power1 和 power2。使用日期时间作为索引,我已经可以随时间计算多个平均值/最大值,并在读取 csv 的单独程序上使用 pandas 绘制图形。 Pandas 非常有趣和强大,还有很多东西要学!但很高兴我得到了结果!谢谢@solve-it!
猜你喜欢
  • 1970-01-01
  • 2017-04-15
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
  • 2019-02-21
  • 1970-01-01
  • 2017-02-13
相关资源
最近更新 更多