Лучший способ извлечь список длительности из списка даты и времени

#python #list #numpy

#питон #Список #numpy

Вопрос:

У меня есть список дат. Я хочу преобразовать это в список, в котором отображаются промежутки времени между датами. Следующий код работает нормально, однако, если я посмотрю на него, он кажется излишним. Сначала я преобразую список в массив numpy, затем создаю массив dureation и преобразую его обратно в список секунд. Я сталкиваюсь с этим много раз, поэтому было бы здорово, если бы кто-нибудь сказал мне, каким наиболее эффективным способом было бы это сделать.

 import datetime;
from numpy import *

times = [datetime.datetime(2014, 6, 23, 18, 56, 30),
 datetime.datetime(2014, 6, 23, 18, 57),
 datetime.datetime(2014, 6, 23, 18, 57, 30),
 datetime.datetime(2014, 6, 23, 18, 58),
 datetime.datetime(2014, 6, 23, 18, 58, 30),
 datetime.datetime(2014, 6, 23, 18, 59),
 datetime.datetime(2014, 6, 23, 18, 59, 30)]

seconds = array(times)
start = times[0]
duration = seconds - start

secs = [];
for item in duration:
    secs.append(item.seconds);

# result: secs = [0, 30, 60, 90, 120, 150, 180]
 

Ответ №1:

Вы можете выполнять вычитание datetime объектов напрямую:

 >>> [(a - times[0]).total_seconds() for a in times]
[0, 30, 60, 90, 120, 150, 180]
 

Когда вы вычитаете два datetime.datetime объекта, вы получаете datetime.timedelta обратно объект, который представляет промежуток времени между ними datetimes . Таким образом, вы можете просто выполнить итерацию по списку, вычесть текущее время из первого раза и использовать total_seconds() метод из timedelta объекта, который он возвращает, чтобы получить разницу в секундах.

Ответ №2:

Что-то вроде этого будет работать (не требуется numpy):

 times = [datetime.datetime(2014, 6, 23, 18, 56, 30),
    datetime.datetime(2014, 6, 23, 18, 57),
    datetime.datetime(2014, 6, 23, 18, 57, 30),
    datetime.datetime(2014, 6, 23, 18, 58),
    datetime.datetime(2014, 6, 23, 18, 58, 30),
    datetime.datetime(2014, 6, 23, 18, 59),
    datetime.datetime(2014, 6, 23, 18, 59, 30)]

start = times[0]
output = [ (t - start).seconds for t in times]

print output
# [0, 30, 60, 90, 120, 150, 180]
 

Редактировать: я вижу, что меня избили! Хорошая работа: D

Ответ №3:

С помощью строки duration = seconds - start вы создаете список временных дельт в numpy:

 >>> duration
[datetime.timedelta(0) datetime.timedelta(0, 30) datetime.timedelta(0, 60) datetime.timedelta(0, 90) datetime.timedelta(0, 120) datetime.timedelta(0, 150) datetime.timedelta(0, 180)]
 

Таким образом, вы можете создать то, что хотите, непосредственно с помощью numpy.vectorize, чтобы создать новый массив, который отделяет общее количество секунд от duration массива.

Если вы делаете это только один раз, вы можете использовать vectorize как функцию удаления, подобную карте:

 >>> vectorize(lambda td: td.total_seconds())(duration)
[   0.   30.   60.   90.  120.  150.  180.]
 

Или сохраните его, чтобы использовать несколько раз:

 >>> v=vectorize(lambda td: td.total_seconds())
>>> v(duration), v(duration*2)
[   0.   30.   60.   90.  120.  150.  180.] [   0.   60.  120.  180.  240.  300.  360.]
 

Преимущество заключается в том, что если вы работаете в numpy, это сохраняет данные в numpy — нет обратного перехода к Python, поскольку это приведет к пониманию списка.

Ответ №4:

numpy.diff должно работать: http://docs.scipy.org/doc/numpy/reference/generated/numpy.diff.html

Это должно быть быстрее, как только ваши списки дат и времени станут большими (не уверен, почему вы используете numpy для вышеупомянутого). Вероятно, вы могли бы получить еще большую производительность, если переключитесь на типы numpy datetime.

 >>> times = numpy.array(times)
>>> diffs =numpy.diff(times)
>>> diffs
array([datetime.timedelta(0, 30), datetime.timedelta(0, 30),
       datetime.timedelta(0, 30), datetime.timedelta(0, 30),
       datetime.timedelta(0, 30), datetime.timedelta(0, 30)], dtype=object)
 

Если вам нужны исходные числа секунд, вы можете получить их с помощью timedelta.total_seconds() метода:

 seconds = [x.total_seconds() for x in diffs]
 

Редактировать:

Если предполагается, что все дельты относятся к первому значению даты и времени, вы можете просто сделать:

 seconds = [x.total_seconds() for x in times - times[0]]
 

В этом нет необходимости diff

Комментарии:

1. Я думаю, что, глядя на вывод OP, им понадобится что-то вроде: np.cumsum([0] [x.total_seconds() for x in diffs])