Python: преобразование секунд в формат даты и времени в столбце данных - PullRequest
1 голос
/ 05 марта 2019

В настоящее время я работаю с большим фреймом данных (12x47800).Один из двенадцати столбцов является столбцом, состоящим из целого числа секунд.Я хочу изменить этот столбец на столбец, состоящий из формата datetime.time.Расписание - это мой фрейм данных, в котором я пытаюсь изменить столбец с именем «depTime».Так как я хочу, чтобы это было datetime.time и оно могло пересечь полночь, я добавил оператор if.Это «работает», но очень медленно, как можно себе представить.Есть ли более быстрый способ сделать это?Мой текущий код, единственный, который я смог получить, это:

for i in range(len(schedule)):
    t_sec = schedule.iloc[i].depTime
    [t_min, t_sec] = divmod(t_sec,60)
    [t_hour,t_min] = divmod(t_min,60)
    if t_hour>23:
        t_hour -= 23
    schedule['depTime'].iloc[i] = dt.time(int(t_hour),int(t_min),int(t_sec))

Заранее спасибо, ребята.

Ps: Я довольно новичок в Python, поэтому, если кто-нибудь сможет мне помочь, ябыл бы очень благодарен:)

Ответы [ 2 ]

1 голос
/ 05 марта 2019

Вы должны попытаться не выполнять полное сканирование на фрейме данных, а вместо этого использовать векторизованный доступ, потому что он обычно намного более эффективен.

К счастью, у панд есть функция, которая делает именно то, что вы просите, to_timedelta:

schedule['depTime'] = pd.to_timedelta(schedule['depTime'], unit='s')

Это на самом деле не формат даты и времени, но это эквивалент панды datetime.timedelta и удобный тип для обработки. Вы можете использовать to_datetime, но закончите с полной датой, близкой к 1970-01-01 ...

Если вам действительно нужны datetime.time объекты, вы можете получить их так:

schedule['depTime'] = pd.to_datetime(schedule['depTime'], unit='s').time

но их менее удобно использовать в кадре данных панд.

1 голос
/ 05 марта 2019

Я добавляю новое решение, которое намного быстрее, чем оригинальное, поскольку оно опирается на векторизованные функции панд, а не на циклы (функции применения панд - это, по сути, оптимизированные циклы в данных).

Я протестировал его с образцом, похожим по размеру на ваш, и разница составляет от 778 до 21,3 мс. Поэтому я определенно рекомендую новую версию.

Оба решения основаны на преобразовании ваших целых секунд в формат timedelta и добавлении его в опорную дату / время. Затем я просто фиксирую компонент времени результирующих datetime.

Новый (более быстрый) вариант:

import datetime as dt

seconds = pd.Series(np.random.rand(50)*100).astype(int) # Generating test data

start = dt.datetime(2019,1,1,0,0) # You need a reference point

datetime_series = seconds.astype('timedelta64[ms]') + dt.datetime(2019,1,1,0,0)

time_series = datetime_series.dt.time

time_series

Оригинал (медленнее) Ответ:

Не самое элегантное решение, но оно делает свое дело.

import datetime as dt

seconds = pd.Series(np.random.rand(50)*100).astype(int) # Generating test data

start = dt.datetime(2019,1,1,0,0) # You need a reference point

time_series = seconds.apply(lambda x: start + pd.Timedelta(seconds=x)).dt.time

time_series
...