列表中的平均时间差

28
我想计算一个列表中日期之间的平均时间差。 虽然下面的方法很好用,但我想知道有没有更聪明的方法?
delta = lambda last, next: (next - last).seconds + (next - last).days * 86400   
total = sum(delta(items[i-1], items[i]) for i in range(1, len(items)))
average = total / (len(items) - 1)

1
在8640的末尾再加一个0是个不错的开始 ;) - aaronasterling
为什么不增加地球的自转速度呢?...猜想你是对的 =) - shinn
4个回答

76

顺便问一句,如果你有一个时间增量或日期时间的列表,为什么还要自己进行任何数学计算呢?

datetimes = [ ... ]

# subtracting datetimes gives timedeltas
timedeltas = [datetimes[i-1]-datetimes[i] for i in range(1, len(datetimes))]

# giving datetime.timedelta(0) as the start value makes sum work on tds 
average_timedelta = sum(timedeltas, datetime.timedelta(0)) / len(timedeltas)

5
+1 是因为 OP 和我都不知道那是可能的。日期时间处理比字符串处理还要无聊 ;) - aaronasterling
我会采用你的平均值计算方法和aaronasterling的方法来获取增量。谢谢 =) - shinn
迭代索引并不是很符合Python的风格。我会选择以下方式:[a - b for a, b in zip(datetimes[:-1], datetimes[1:])] - abukaj
3
在这个例子中,应该是 datetimes[i]-datetimes[i-1] - sachleen
聪明的技巧是将datetime.timedelta(0)设置为起始值,以使sum函数正常工作。另外,我注意到np.sum函数不起作用,必须使用原生的"sum"函数。但是Franciska的方法也有效,并且看起来更简洁。 - undefined

8
如果您有一个timedelta列表:
import pandas as pd
avg=pd.to_timedelta(pd.Series(yourtimedeltalist)).mean()

3

试试这个:

from itertools import izip

def average(items):   
    total = sum((next - last).seconds + (next - last).days * 86400
                for next, last in izip(items[1:], items))
     return total / (len(items) - 1)

在我看来,这样做更易读。为了让对数学不太敏感的读者理解你是如何计算每个delta的,可以添加一条注释。值得一提的是,一个生成器表达式具有最少的(并且我认为是最不慢的)操作码指令。

  # The way in your question compiles to....
  3           0 LOAD_CONST               1 (<code object <lambda> at 0xb7760ec0, file 

"scratch.py", line 3>)
              3 MAKE_FUNCTION            0
              6 STORE_DEREF              1 (delta)

  4           9 LOAD_GLOBAL              0 (sum)
             12 LOAD_CLOSURE             0 (items)
             15 LOAD_CLOSURE             1 (delta)
             18 BUILD_TUPLE              2
             21 LOAD_CONST               2 (<code object <genexpr> at 0xb77c0a40, file "scratch.py", line 4>)
             24 MAKE_CLOSURE             0
             27 LOAD_GLOBAL              1 (range)
             30 LOAD_CONST               3 (1)
             33 LOAD_GLOBAL              2 (len)
             36 LOAD_DEREF               0 (items)
             39 CALL_FUNCTION            1
             42 CALL_FUNCTION            2
             45 GET_ITER            
             46 CALL_FUNCTION            1
             49 CALL_FUNCTION            1
             52 STORE_FAST               1 (total)

  5          55 LOAD_FAST                1 (total)
             58 LOAD_GLOBAL              2 (len)
             61 LOAD_DEREF               0 (items)
             64 CALL_FUNCTION            1
             67 LOAD_CONST               3 (1)
             70 BINARY_SUBTRACT     
             71 BINARY_DIVIDE       
             72 STORE_FAST               2 (average)
             75 LOAD_CONST               0 (None)
             78 RETURN_VALUE        
None
#
#doing it with just one generator expression and itertools...

  4           0 LOAD_GLOBAL              0 (sum)
              3 LOAD_CONST               1 (<code object <genexpr> at 0xb777eec0, file "scratch.py", line 4>)
              6 MAKE_FUNCTION            0

  5           9 LOAD_GLOBAL              1 (izip)
             12 LOAD_FAST                0 (items)
             15 LOAD_CONST               2 (1)
             18 SLICE+1             
             19 LOAD_FAST                0 (items)
             22 CALL_FUNCTION            2
             25 GET_ITER            
             26 CALL_FUNCTION            1
             29 CALL_FUNCTION            1
             32 STORE_FAST               1 (total)

  6          35 LOAD_FAST                1 (total)
             38 LOAD_GLOBAL              2 (len)
             41 LOAD_FAST                0 (items)
             44 CALL_FUNCTION            1
             47 LOAD_CONST               2 (1)
             50 BINARY_SUBTRACT     
             51 BINARY_DIVIDE       
             52 RETURN_VALUE        
None

特别是,放弃使用lambda可以避免创建闭包、构建元组和加载两个闭包。无论如何,这种关注性能的方式有点荒谬,但知道底层发生了什么很好。最重要的是可读性,我认为这种做法在可读性方面得分很高。

是的,这样好多了。谢谢! - shinn
@shinn,如果您接受THC4k的答案,那么我可以删除这个回答。 - aaronasterling
你不应该删除它。我喜欢使用izip的方式。 - shinn
缩进不匹配! ;) - abukaj

0
sum(timedelta_list ,datetime.timedelta())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接