我有一个名为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()
,但当然没有用。关于如何避免这种循环的任何想法?
由于
答案 0 :(得分:12)
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
,请考虑问自己为什么要在第一时间进行增量(而不是timedelta64
s),然后使用{ {1}}表达。它不那么原生,但出于某种原因它更快。
答案 1 :(得分:9)
import numpy as np
helper = np.vectorize(lambda x: x.total_seconds())
dt_sec = helper(dt)
答案 2 :(得分:0)
我喜欢prgao建议使用np.vectorize
。如果您只想要一个Python列表,您还可以执行以下操作:
dt_sec = map(datetime.timedelta.total_seconds, dt)
答案 3 :(得分:0)
一种方便而优雅的方法是使用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
答案 4 :(得分:-2)
您可以使用“列表理解”:
dt_sec = [delta.total_seconds() for delta in dt]
在幕后,numpy应该把它翻译成一个非常快速的操作。