首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从定期读数中提取睡眠质量分数

从定期读数中提取睡眠质量分数
EN

Code Review用户
提问于 2016-03-05 11:01:40
回答 2查看 116关注 0票数 4

如何优化下一个函数,使其工作得更快?该函数必须准备一个列表以放入CSV文件。该列表必须包含从scores中计算的每分钟平均睡眠百分比的值--表格[阶段,时间]的列表,其中的阶段可以是“S”、“R”或“W”,而时间是'%d %H:%M:%S'格式的;如下所示:

代码语言:javascript
复制
scores = [['S', '01 12:11:00'], ['S', '01 12:11:20'], ['W', '01 12:11:40'], ['S', '01 12:12:00'], ...]

函数还必须按小时和日对计数值进行分组,因此输出应该如下所示:

代码语言:javascript
复制
quantities = [[1, 12, 11, 0.66], [1, 12, 12, 0.33], [1, 12, 13, 1], ...]
代码语言:javascript
复制
from itertools import product
import datetime

def sleep_quantity(scores):
    global quantities
    quantities = []
    for day, hour, minute in product(range(1,4), range(24), range(60)):
        sleep = 0
        total = 0
        quantity = []
        for line in scores:
            time = datetime.datetime.strptime(line[1], '%d %H:%M:%S')
            stage = line[0]
            if time.hour == hour and time.day == day and time.minute == minute:
                total += 1
                if stage == 'S' or stage == 'R':
                    sleep += 1
        if total != 0:
            sleep_per_minute = sleep / total
            quantity.append(hour)
            quantity.append(day)
            quantity.append(minute)
            quantity.append(sleep_per_minute)
            quantities.append(quantity) #for export to CSV
    return quantities
EN

回答 2

Code Review用户

发布于 2016-03-05 13:05:21

首先,quantities全局功能听起来是不必要的。该值在开始时被清除,并且该值也从函数中返回,不需要关闭全局。

更新quantity的方式可以简化得多,方法是立即追加文字列表,而不是更新变量:

代码语言:javascript
复制
quantities.append([hour, day, minute, sleep / total])

现在,另一个快速建议也是在内部for循环中使用析构:

代码语言:javascript
复制
    for (stage, time_string) in scores:

最后,结果中对小时、日、分钟的排序意味着列表上的常规sort方法不足以以合理的方式对列表进行排序--我建议将其按递减顺序排列,即天、时、分钟。

编辑:在我发布之前已经更新了,但我认为我的假设仍然有效。(不幸的是,对于这个函数为什么会这样做,没有太多的解释。)

然而,现在需要注意的是,设置迭代的方式不如另一种方式有效:product列表是4320元素,而scores列表可能要短得多--听起来应该反过来嵌套它们。

考虑到对代码应该做什么没有任何解释,我将对语义进行一些猜测。现在,我们在一分钟的步骤中迭代三天,检查scores中的任何元素是否匹配,如果匹配,则执行一些操作。对于total,我们会及时积累所有匹配,如果得到匹配,就会追加到quantities列表中。

这意味着,我认为,您正在寻找列表中的所有时间戳,这些时间戳同时发生,然后将时间戳的“类型”相加,并为有匹配的每个时刻追加一个结果。

这可以在排序(时间戳)和累积连续范围方面写得更好:

代码语言:javascript
复制
def sleep_quantity2(scores):
    buckets = {}

    for stage, time_string in scores:
        time = datetime.datetime.strptime(time_string, '%d %H:%M:%S')

        stages = buckets.get(time, [0, 0])
        buckets[time] = stages

        stages[0] += 1
        if stage == "R" or stage == "S":
            stages[1] += 1

    quantities = []
    for time, stages in buckets.iteritems():
        quantities.append([time.day, time.hour, time.minute, stages[1] / stages[0]])

    quantities.sort()

    return quantities

因此,流程是:将条目累加到桶中,每一刻一个桶,同时更新该桶的数字,然后在结束时遍历所有桶并生成结果列表,并且由于顺序是任意的,因此再次对它们进行排序,使其与前面方法的输出相匹配。

现在,如果您愿意,您仍然可以使用yield来代替累积列表,并在Python2.7中使用xrange而不是range

哦,运行一个分析器。

作为参考,我最后将它与以下代码进行了比较:

代码语言:javascript
复制
def sleep_quantity1(scores):
    quantities = []
    for day, hour, minute in product(range(1, 4), range(24), range(60)):
        sleep = 0
        total = 0
        for (stage, time_string) in scores:
            time = datetime.datetime.strptime(time_string, '%d %H:%M:%S')
            if time.hour == hour and time.day == day and time.minute == minute:
                total += 1
                if stage == 'S' or stage == 'R':
                    sleep += 1
        if total != 0:
            quantities.append([day, hour, minute, sleep / total])
    return quantities
票数 3
EN

Code Review用户

发布于 2016-03-05 12:09:09

发生器

您不需要构建两个列表,一个内部列表和一个外部列表,并将内部列表附加到外部列表中,您可以简化很多,只需yield结果即可。(您可能需要对这个新函数的输出调用list )

代码语言:javascript
复制
def sleep_quantity(scores):
    for day, hour, minute in product(range(1,4), range(24), range(60)):
        sleep = 0
        total = 0
        for line in scores:
            time = datetime.datetime.strptime(line[1], '%d %H:%M:%S')
            stage = line[0]
            if time.hour == hour and time.day == day and time.minute == minute:
                total += 1
                if stage == 'S' or stage == 'R':
                    sleep += 1
        if total != 0:
            sleep_per_minute = sleep / total
            yield [hour, day, minute, sleep_per_minute]
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/121977

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档