2013-09-26 1 views
8

У меня есть массив numpy, называемый dt. Каждый элемент имеет тип datetime.timedelta. Например:элегантный способ преобразования массива numpy, содержащий datetime.timedelta в секунды в python 2.7

>>>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(), но, конечно, это не сработало. любая идея о том, как избежать этого цикла?

Благодаря

ответ

9
import numpy as np 

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

Почему бы не использовать 'x.seconds' в' lambda'? Кроме того, если массив представляет собой плоский одномерный массив, это 'map (lambda x: x.total_seconds(), dt)' быстрее? – wflynny

+0

уверен и прав (нужно было бы преобразовать список в массив в конце). – prgao

+0

Я не знал о векторизации ... какая полезная функция! Благодаря! – ccbunney

-2

Вы можете использовать "список понимание":

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

За кулисы, NumPy должен перевести это на довольно скорую операцию.

+0

'numpy' ничего не делает за кулисами. Похоже, это будет медленнее, чем цикл над обычным «списком». – Veedrac

10

numpy имеет свои собственные datetime и timedelta форматов. Просто используйте их;).

Set-до, например:

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 с), в первую очередь, а затем использовать выражение numpy.vectorize. Он менее родной, но по какой-то причине он быстрее.

0

Мне нравится использование np.vectorize как предложено prgao. Если вы просто хотите список Python, вы также можете сделать следующее:

dt_sec = map(datetime.timedelta.total_seconds, dt) 
Смежные вопросы