在 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
有自己的datetime
和timedelta
格式。只需使用它们;)。
例如设置:
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 倍。
如果您永远不会再使用那些timedelta
s,请考虑首先问自己为什么要制作增量(而不是timedelta64
s),然后使用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.Series
和dt.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 输出分配给元组(二维数组)