Як перетворити дати у фреймі даних Pandas у тип даних „дата“?


104

У мене є кадр даних Pandas, один із стовпців містить рядки дат у форматі YYYY-MM-DD

Наприклад, '2013-10-28'

На даний момент dtypeколона є object.

Як перетворити значення стовпців у формат дати Pandas?

Відповіді:


109

Використовуйте 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 наприкінці кожного побачення?
користувач7289

1
Мітка часу панди має як дату, так і час. Ви маєте на увазі перетворити його на об'єкт дати python?
waitkuo

7
Ви можете перетворити його доdf['time'] = [time.date() for time in df['time']]
waitkuo

3
що означає [ns], чи можете ви зробити текстовий рядок датою та видалити часову частину цієї дати?
yoshiserry

1
@yoshiserry - це наносекунди, і це спосіб збереження дат під капотом після їх правильного перетворення (епоха в наносекундах).
Andy Hayden,

113

По суті еквівалент @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'])

Кидає a

ValueError: Unknown string format

Це означає, що у вас є недійсні (непримусові) значення. Якщо у вас все в порядку з їх перетворенням pd.NaT, ви можете додати errors='coerce'аргумент до to_datetime:

df['time'] = pd.to_datetime(df['time'], errors='coerce')

Привіт, хлопці, @AndyHayden, чи можете ви вилучити часову частину з дати? Мені не потрібна ця частина?
yoshiserry

У пандах 0.13.1 кінцеві 00: 00: 00 с не відображаються.
Andy Hayden,

а як щодо інших версій, як їх видалити / і чи не відображати?
yoshiserry

Я не думаю, що це можна зробити приємно, є обговорення, щоб додати date_format, наприклад float_format (що ви бачили). Я все одно рекомендую оновити.
Енді Хайден

моя проблема полягає в тому, що моя дата в такому форматі ... 41516.43, і я отримую цю помилку. Я очікував би, що це поверне щось на зразок 03.02.2014 у новій колонці ?! ПОМИЛКА: #convert значення дати в стовпці "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

35

Я думаю, багато даних надходить у 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/…
Састібе,

24

Тепер ви можете це зробити df['column'].dt.date

Зауважте, що для об’єктів datetime, якщо ви не бачите години, коли всі вони 00:00:00, це не панди. Це ноутбук iPython, який намагається зробити речі виглядають красиво.


2
Цей не працює для мене, він скаржиться: Можна використовувати лише .dt Accessor зі значеннями,
схожими на

2
Вам, можливо, доведеться df[col] = pd.to_datetime(df[col])спочатку перетворити стовпець на об'єкти часу.
szeitlin

Проблема з цією відповіддю полягає в тому, що він перетворює стовпець, dtype = objectякий займає значно більше пам’яті, ніж істина datetime dtypeу пандах.
elPastor

6

Ще один спосіб зробити це, і це добре працює, якщо у вас є кілька стовпців для перетворення в datetime.

cols = ['date1','date2']
df[cols] = df[cols].apply(pd.to_datetime)

Питання задайте дату, а не дату і час.
Марк Андерсен,

@MarkAndersen до тих пір, поки dateу ваших стовпцях є лише значення, перехід на datetime збереже лише відповідну інформацію. Якщо ви однозначно конвертуєте, використовуючи df['datetime_col'].dt.dateце, ви отримаєте objectdtype; втрата в управлінні пам'яттю.
Сумант Лазар


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]

0

Для повноти, інший варіант, який може бути не найпростішим, трохи схожий на той, що запропонував @SSS, але використання, скоріше, бібліотеки дат та часу:

import datetime
df["Date"] = df["Date"].apply(lambda x: datetime.datetime.strptime(x, '%Y-%d-%m').date())
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.