在 python 2.7 中将包含 datetime.timedelta 的 numpy 数组转换为秒的优雅方法

Posted

技术标签:

【中文标题】在 python 2.7 中将包含 datetime.timedelta 的 numpy 数组转换为秒的优雅方法【英文标题】:elegant way of convert a numpy array containing datetime.timedelta into seconds in python 2.7 【发布时间】:2013-10-03 01:28:36 【问题描述】:

我有一个名为 dt 的 numpy 数组。每个元素的类型为datetime.timedelta。例如:

>>>dt[0]
datetime.timedelta(0, 1, 36000)

如何将dt 转换为数组dt_sec,它只包含秒数而不循环?我目前的解决方案(可行,但我不喜欢)是:

dt_sec = zeros((len(dt),1))
for i in range(0,len(dt),1):
    dt_sec[i] = dt[i].total_seconds()

我尝试使用dt.total_seconds(),但它当然没有用。关于如何避免这个循环的任何想法?

谢谢

【问题讨论】:

【参考方案1】:

numpy 有自己的datetimetimedelta 格式。只需使用它们;)。

例如设置:

import datetime
import numpy

times = numpy.array([datetime.timedelta(0, 1, 36000)])

代码:

times.astype("timedelta64[ms]").astype(int) / 1000
#>>> array([ 1.036])

由于人们似乎没有意识到这是最好的解决方案,以下是 timedelta64 数组与 datetime.datetime 数组的一些时序:

SETUP="
import datetime
import numpy

times = numpy.array([datetime.timedelta(0, 1, 36000)] * 100000)
numpy_times = times.astype('timedelta64[ms]')
"

python -m timeit -s "$SETUP" "numpy_times.astype(int) / 1000"
python -m timeit -s "$SETUP" "numpy.vectorize(lambda x: x.total_seconds())(times)"
python -m timeit -s "$SETUP" "[delta.total_seconds() for delta in times]"

结果:

100 loops, best of 3: 4.54 msec per loop
10 loops, best of 3: 99.5 msec per loop
10 loops, best of 3: 67.1 msec per loop

初始转换所花费的时间大约是向量化表达式的两倍,但从那时起到该timedelta 数组上的每个操作都将快大约 20 倍。


如果您永远不会再使用那些timedeltas,请考虑首先问自己为什么要制作增量(而不是timedelta64s),然后使用numpy.vectorize 表达式。它不那么原生,但由于某种原因它更快。

【讨论】:

【参考方案2】:
import numpy as np

helper = np.vectorize(lambda x: x.total_seconds())
dt_sec = helper(dt)

【讨论】:

为什么不在lambda 中使用x.seconds?另外,如果数组是平面一维数组,map(lambda x: x.total_seconds(), dt) 是否更快? 确定和正确(最终必须将列表转换为数组)。 我不知道矢量化...多么有用的功能!谢谢!【参考方案3】:

一种方便而优雅的方式是使用pandas.Seriesdt.total_seconds 属性:

import numpy as np
import pandas as pd

# create example datetime arrays
arr1 = np.array(['2007-07-13', '2006-01-13', '2010-08-13'], dtype='datetime64')
arr2 = np.array(['2007-07-15', '2006-01-18', '2010-08-22'], dtype='datetime64')

# timedelta array
td = arr2 - arr1

# get total seconds
pd.Series(td).dt.total_seconds()
0    172800.0
1    432000.0
2    777600.0
dtype: float64

【讨论】:

与此答案相关的一些链接:Series.dt:pandas.pydata.org/docs/reference/api/pandas.Series.dt.htmlSeries.dt.total_seconds:pandas.pydata.org/docs/reference/api/…【参考方案4】:

我喜欢prgao 所建议的np.vectorize 的使用。如果你只想要一个 Python 列表,你也可以这样做:

dt_sec = map(datetime.timedelta.total_seconds, dt)

【讨论】:

【参考方案5】:

您可以使用“列表理解”:

dt_sec = [delta.total_seconds() for delta in dt]

在幕后,numpy 应该将其转化为非常快速的操作。

【讨论】:

numpy 并没有在幕后做任何事情。哎呀,它可能会比普通 list 上的循环慢。

以上是关于在 python 2.7 中将包含 datetime.timedelta 的 numpy 数组转换为秒的优雅方法的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 3.4 中将 datetime.time 转换为 datetime.timedelta

在 Python 中将 datetime.date 转换为 UTC 时间戳

尝试在 Python 2.7 中将 SQL*Plus 输出分配给元组(二维数组)

Python:在数据框列中将秒转换为日期时间格式

仅在 Python 中将 datetime 对象转换为日期字符串

在 Python 中将 N 秒添加到 datetime.time 的标准方法是啥?