Преобразование части строк информационного кадра из чисел в дату и время, но получили странные числа

1

Я пытаюсь преобразовать некоторые строки данных из чисел в datetime, но получил странные числа.

import pandas as pd 
import datetime as dt

df = pd.DataFrame({'col': [dt.datetime(2018,1,1), 1.2, 3.2, 2.1]})
mask = df['col'].apply(lambda x:type(x)==float) # find rows that are numbers
# convert numbers to datetime
df.loc[mask, 'col'] = df.loc[mask, 'col'].apply(
    lambda x: dt.datetime(2018,5,1) + dt.timedelta(days=(x*365)))
print(df) 

col
0  2018-01-01 00:00:00
1  1562976000000000000
2  1626048000000000000
3  1591358400000000000

Почему получилось огромное количество строк в рядах 1 ~ 3? Я думаю, причина в том, что тип элементов в разных строках отличается. Но я действительно хочу сделать изменения в кадре данных. Какие-либо предложения? Спасибо!

Теги:
pandas
datetime

2 ответа

0
Лучший ответ

Причина в том, что у вас есть столбец смешанных типов (datetimes и floats). Панды, будучи сбиты с толку, полагают, что присваиваемые значения также являются поплавками и пытаются преобразовать даты в индексе с 1 по 3 в числа (то, что вы видите, - это число наносекунд с эпохи в 1970 году).

Здесь векторизованное исправление с использованием pd.to_numeric, pd.to_timedelta и pd.to_datetime:

((pd.to_timedelta(pd.to_numeric(df.col, errors='coerce')) * 365 
    + pd.to_datetime('2018-05-01')).fillna(df.col)
)

0   2018-01-01 00:00:00.000000000
1   2018-05-01 00:00:00.000000365
2   2018-05-01 00:00:00.000001095
3   2018-05-01 00:00:00.000000730
Name: col, dtype: datetime64[ns]
  • 0
    Понятно! Спасибо вам большое!
0

Я не очень хорошо знаком с пандами, но он похож на серию datetime, которую вы создаете в df.loc[mask, 'col'].apply(lambda x: dt.datetime(2018,5,1) + dt.timedelta(days=(x*365))) получает неявное преобразование в целочисленный тип данных, когда он назначен в df.loc[mask, 'col']. Я не уверен, почему Пандас сделает это, но это, похоже, вызывает проблемы. Вот быстрое решение:

import pandas as pd
import datetime as dt

df = pd.DataFrame({'col': [dt.datetime(2018, 1, 1), 1.2, 3.2, 2.1]})

df['col'] = df['col'].apply(lambda x: dt.datetime(2018, 5, 1) + dt.timedelta(days=(x * 365)) if type(x) == float else x)

То, что я сбиваю с толку, - это то, почему Pandas преобразует некоторые элементы серии (элементы в индексе 1-3) в целые числа, оставляя другие элементы (элемент с индексом 0) как есть. Другими словами, зачем преобразовывать элементы серии, которые назначаются в серию (df.loc[mask, 'col'].apply(lambda x: dt.datetime(2018, 5, 1) + dt.timedelta(days=(x * 365))) от типа данных datetimes до целых чисел, не преобразовывая элемент, который уже существует в серии из datetime в integer? Кажется, мне неинтуитивно, но, возможно, мне что-то не хватает. @coldspeed, вы можете уточнить?

  • 0
    Спасибо за ответ, Крис! Ваше решение должно работать для меня. Но мне все еще любопытно, почему мой старый метод не сработал. Выходные данные - просто большие целые числа. Они даже не отметка времени. Я пытался использовать datetime.datetime.fromtimestamp () для преобразования целых чисел в datetime, но это не сработало.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню