Преобразование кадра данных в список кортежей изменяет datetime.datetime на int

avatar
luser3228561
1 июля 2021 в 20:13
144
2
0

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

Я обнаружил, что объекты datetime.datetime преобразуются в длинные целые числа, например 1622623719000000000.

Мне нужно рассчитать разницу во времени между каждой строкой, поэтому я подумал: «Хорошо, я не силен в python/pandas, но я знаю, что могу сделать datetime.fromtimestamp(1622623719000000000), чтобы вернуть объект datetime.

К сожалению, datetime.fromtimestamp(1622623719000000000) выдает OSError: [Errno 22] Invalid argument.

Итак, отправляйтесь в Google/SO, чтобы найти решение. Я нахожу этот пример, который показывает деление длинного целого числа на 1e3. Я пытаюсь это сделать, но все равно получаю «неверный аргумент».

Я играю с делением длинного int, и деление на 1e9 дает мне самое близкое к исходному значению datetime.datetime, но не совсем.

Как успешно преобразовать long int обратно в правильное значение datetime?

Код для преобразования строкового формата в дату и время:

df.start_time = pd.to_datetime(df.report_date + " " + df.start_time)

Информация о кадре данных:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 46 entries, 0 to 45
Data columns (total 19 columns):
report_date      46 non-null object
...
...
...
start_time       46 non-null datetime64[ns]
...
...
...

dtypes: datetime64[ns](1), float64(7), int64(1), object(10)
memory usage: 6.9+ KB
None

Мой тестовый код:

print("DF start time", df.start_time[5], "is type", type(df.start_time[5]))
print("list start time", tup_list[5][7], "is type", type(tup_list[5][7]),"\n")

print("Convert long int in row tuple to datetime")
print(datetime.fromtimestamp(int(1622623719000000000/1e9)))

Вывод:

DF start time 2021-06-02 08:16:33 is type <class 'pandas._libs.tslibs.timestamps.Timestamp'>
list start time 1622623719000000000 is type <class 'int'> 

Convert int in row tuple to datetime
2021-06-02 03:48:39
Источник

Ответы (2)

avatar
luser3228561
9 июля 2021 в 18:42
0

Я решил эту проблему и, вероятно, изначально должен был пойти с ней.

Изначально я преобразовал свой фрейм данных в список кортежей для более быстрой обработки строк:

df.to_records(index=False).tolist()

К сожалению, при преобразовании значения в df.start_time были преобразованы из <class 'pandas._libs.tslibs.timestamps.Timestamp'> в <class int>

Решение:

df.to_dict('records')

Это сохранило данные в df.start_time как Timestamp типы:

'start_time': Timestamp('2021-06-02 08:16:33')

Усвоенный урок.

avatar
Corralien
1 июля 2021 в 20:49
0

Измените тип столбца start_time, чтобы преобразовать Timestamp в целое число (наносекунды):

df = pd.DataFrame({'start_time': ['2021-06-02 08:16:33']}) \
       .astype({'start_time': 'datetime64'})

>>> df
           start_time
0 2021-06-02 08:16:33

>>> df['start_time'].astype(int)
0    1622621793000000000  # NOT 1622623719000000000
Name: start_time, dtype: int64

>>> pd.to_datetime(1622621793000000000)  # Right
Timestamp('2021-06-02 08:16:33')

>>> pd.to_datetime(1622623719000000000)  # Wrong
Timestamp('2021-06-02 08:48:39')
Corralien
1 июля 2021 в 20:50
0

или, может быть, ваша индексация не очень хороша. Каковы значения до и после Timestamp('2021-06-02 08:48:39') в вашем фрейме данных?

luser3228561
6 июля 2021 в 14:03
0

Я скопировал/вставил приведенный выше код, чтобы преобразовать столбец в astype(int) и получил TypeError: cannot astype a datetimelike from [datetime64[ns]] to [int32]. Мой исходный код для преобразования из строкового формата в дату и время - df.start_time = pd.to_datetime(df.start_time)

Corralien
6 июля 2021 в 15:35
0

Обновите свой код образцом исходного фрейма данных и выводом df.info().

luser3228561
6 июля 2021 в 19:25
0

Добавлено в соответствии с просьбой к исходному сообщению.

Corralien
6 июля 2021 в 19:40
0

Какая у вас версия Python? Вы работаете на 32-битной машине (int32)? Если вы хотите решить проблему, я думаю, вам следует использовать df['start_time'].astype(np.int64). Я могу воспроизвести вашу ошибку с помощью: df['start_time'].astype(np.int32)

luser3228561
7 июля 2021 в 13:15
0

Python версии 3.7, 64-разрядная версия. Я использовал df['start_time'].astype(np.int64) для создания numpy.int64, и обратное преобразование в метку времени работает, когда я конвертирую df.start_time обратно в Timestamp. Но, чтобы быстрее обрабатывать мою логику, я преобразовываю df в список кортежей через df.to_records(index=False).tolist() Проблема, по-видимому, заключается в том, что когда строки df преобразуются в список кортежей, df.start_time преобразуется из <class 'numpy.int64'> в <class 'int'>, 1622621793000000000 в df (верно) на 1622623719000000000 в кортеже (неверно).

Corralien
7 июля 2021 в 13:53
0

Мой метод недостаточно быстрый? Кажется, вы выполняете много операций (просмотр и индексация списка, которые могут быть медленными.

luser3228561
7 июля 2021 в 18:34
0

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