Как преобразовать даты во фрейме данных Pandas в тип данных «дата»?

105

У меня есть фрейм данных Pandas, один из столбцов содержит строки даты в формате YYYY-MM-DD

Например, '2013-10-28'

На данный момент dtypeстолбец есть object.

Как преобразовать значения столбцов в формат даты Pandas?

user7289
источник

Ответы:

111

Используйте astype

In [31]: df
Out[31]: 
   a        time
0  1  2013-01-01
1  2  2013-01-02
2  3  2013-01-03

In [32]: df['time'] = df['time'].astype('datetime64[ns]')

In [33]: df
Out[33]: 
   a                time
0  1 2013-01-01 00:00:00
1  2 2013-01-02 00:00:00
2  3 2013-01-03 00:00:00
ожидание
источник
1
Хорошо - спасибо - как мне избавиться от 00:00:00 в конце каждого свидания?
user7289
1
Отметка времени панды имеет дату и время. Вы имеете в виду преобразовать его в объект даты Python?
waitkuo
7
Вы можете конвертировать егоdf['time'] = [time.date() for time in df['time']]
waitkuo
3
что означает [ns], можете ли вы сделать текстовую строку датой и удалить часть времени из этой даты?
yoshiserry
1
@yoshiserry - это наносекунды, и это способ хранения дат под капотом после правильного преобразования (время эпохи в наносекундах).
Энди Хайден
114

По сути эквивалент @waitingkuo, но я бы использовал to_datetimeздесь (он кажется немного чище и предлагает некоторые дополнительные функции, например dayfirst):

In [11]: df
Out[11]:
   a        time
0  1  2013-01-01
1  2  2013-01-02
2  3  2013-01-03

In [12]: pd.to_datetime(df['time'])
Out[12]:
0   2013-01-01 00:00:00
1   2013-01-02 00:00:00
2   2013-01-03 00:00:00
Name: time, dtype: datetime64[ns]

In [13]: df['time'] = pd.to_datetime(df['time'])

In [14]: df
Out[14]:
   a                time
0  1 2013-01-01 00:00:00
1  2 2013-01-02 00:00:00
2  3 2013-01-03 00:00:00

Обработка ValueErrors
Если вы столкнетесь с ситуацией, когда

df['time'] = pd.to_datetime(df['time'])

Бросает

ValueError: Unknown string format

Это означает, что у вас есть недопустимые (непринудительные) значения. Если вы согласны с их преобразованием в pd.NaT, вы можете добавить errors='coerce'аргумент в to_datetime:

df['time'] = pd.to_datetime(df['time'], errors='coerce')
Энди Хайден
источник
Привет, ребята, @AndyHayden вы можете убрать часть времени из даты? Мне не нужна эта часть?
yoshiserry
В pandas 0.13.1 завершающие 00: 00: 00 не отображаются.
Энди Хайден
а как насчет других версий, как их убрать / и не отобразить?
yoshiserry
Я не думаю, что это можно сделать хорошим способом, обсуждается добавление date_format, например float_format (которое вы видели). Я все равно рекомендую обновиться.
Энди Хайден
Моя проблема в том, что моя дата находится в этом формате ... 41516.43, и я получаю эту ошибку. Я ожидал, что он вернет что-то вроде 2014-02-03 в новом столбце ?! ОШИБКА: # преобразовать значения дат в столбце "load_date" в даты budget_dataset ['date_last_load'] = pd.to_datetime (budget_dataset ['load_date']) budget_dataset -c: 2: SettingWithCopyWarning: Значение пытается быть установлено на копия фрагмента из DataFrame. Попробуйте вместо этого использовать .loc [row_index, col_indexer] = value
yoshiserry
36

Я предполагаю, что много данных поступает в Pandas из файлов CSV, и в этом случае вы можете просто преобразовать дату во время первоначального чтения CSV:

dfcsv = pd.read_csv('xyz.csv', parse_dates=[0])где 0 относится к столбцу, в котором находится дата.
Вы также можете добавить , index_col=0туда, если хотите, чтобы дата была вашим индексом.

См. Https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

фантастический
источник
Спасибо, это именно то, что мне нужно. Документация переместилась, хотя, вы можете найти его здесь: pandas.pydata.org/pandas-docs/stable/reference/api/...
Sastibe
24

Теперь ты можешь сделать df['column'].dt.date

Обратите внимание, что для объектов datetime, если вы не видите час, когда они все 00:00:00, это не панды. Ноутбук iPython пытается сделать вещи красивыми.

Szeitlin
источник
2
У меня этот не работает, он жалуется: может использовать аксессор .dt только со значениями типа datetime
smishra
2
вам может потребоваться df[col] = pd.to_datetime(df[col])сначала преобразовать столбец в объекты даты и времени.
szeitlin
Проблема с этим ответом заключается в том, что он преобразует столбец, dtype = objectкоторый занимает значительно больше памяти, чем истинный datetime dtypeв pandas.
elPastor
6

Другой способ сделать это, и он хорошо работает, если у вас есть несколько столбцов для преобразования в datetime.

cols = ['date1','date2']
df[cols] = df[cols].apply(pd.to_datetime)
SSS
источник
Вопрос задайте дату, а не дату и время.
Марк Андерсен
@MarkAndersen, поскольку у вас есть dateтолько значения в столбцах, преобразование в datetime сохранит только относящуюся к делу информацию. Если вы явно конвертируете с помощью df['datetime_col'].dt.date, это приведет к objectdtype; потеря в управлении памятью.
Сумант Лазарь,
6

Если вы хотите получить формат DATE, а не DATETIME:

df["id_date"] = pd.to_datetime(df["id_date"]).dt.date
Дэвид Валенсуэла Уррутия
источник
1

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

#set an index by dates
df.set_index(['time'], drop=True, inplace=True)

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

#Convert to daily dates
df.index = pd.DatetimeIndex(data=df.index)

#Convert to monthly dates
df.index = df.index.to_period(freq='M')

#Convert to strings
df.index = df.index.strftime('%Y-%m')

#Convert to daily dates
df.index = pd.DatetimeIndex(data=df.index)

Для краткости я не показываю, что запускаю следующий код после каждой строки выше:

print(df.index)
print(df.index.dtype)
print(type(df.index))

Это дает мне следующий результат:

Index(['2013-01-01', '2013-01-02', '2013-01-03'], dtype='object', name='time')
object
<class 'pandas.core.indexes.base.Index'>

DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03'], dtype='datetime64[ns]', name='time', freq=None)
datetime64[ns]
<class 'pandas.core.indexes.datetimes.DatetimeIndex'>

PeriodIndex(['2013-01', '2013-01', '2013-01'], dtype='period[M]', name='time', freq='M')
period[M]
<class 'pandas.core.indexes.period.PeriodIndex'>

Index(['2013-01', '2013-01', '2013-01'], dtype='object')
object
<class 'pandas.core.indexes.base.Index'>

DatetimeIndex(['2013-01-01', '2013-01-01', '2013-01-01'], dtype='datetime64[ns]', freq=None)
datetime64[ns]
<class 'pandas.core.indexes.datetimes.DatetimeIndex'>
Тед М.
источник
0

Попробуйте преобразовать одну из строк в метку времени с помощью функции pd.to_datetime, а затем используйте .map для сопоставления формуляра со всем столбцом

Мванаиди Николь
источник
0
 #   Column          Non-Null Count   Dtype         
---  ------          --------------   -----         
 0   startDay        110526 non-null  object
 1   endDay          110526 non-null  object

import pandas as pd

df['startDay'] = pd.to_datetime(df.startDay)

df['endDay'] = pd.to_datetime(df.endDay)

 #   Column          Non-Null Count   Dtype         
---  ------          --------------   -----         
 0   startDay        110526 non-null  datetime64[ns]
 1   endDay          110526 non-null  datetime64[ns]
DonDrey
источник
0

Для полноты картины, другой вариант, который может быть не самым простым, немного похожий на тот, который предлагает @SSS, но с использованием библиотеки datetime:

import datetime
df["Date"] = df["Date"].apply(lambda x: datetime.datetime.strptime(x, '%Y-%d-%m').date())
рубебоп
источник