Como faço para converter datas em um quadro de dados Pandas em um tipo de dados 'data'?

104

Eu tenho um quadro de dados do Pandas, uma das colunas contém strings de data no formato YYYY-MM-DD

Por exemplo '2013-10-28'

No momento em que o dtypeda coluna é object.

Como faço para converter os valores da coluna para o formato de data do Pandas?

user7289
fonte

Respostas:

109

Use 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
esperandokuo
fonte
1
Legal - obrigado - como faço para me livrar das 00:00:00 no final de cada encontro?
user7289
1
O carimbo de data / hora do pandas tem data e hora. Você quer dizer convertê-lo em um objeto de data python?
waitingkuo
7
Você pode convertê-lodf['time'] = [time.date() for time in df['time']]
esperandokuo
3
o que significa [ns], você pode transformar a string de texto em uma data e remover a parte da hora dessa data?
yoshiserry
1
@yoshiserry são nanossegundos e é a forma como as datas são armazenadas sob o capô, uma vez convertidas corretamente (tempo de época em nanossegundos).
Andy Hayden
113

Essencialmente equivalente a @waitingkuo, mas eu usaria to_datetimeaqui (parece um pouco mais limpo e oferece algumas funcionalidades adicionais, por exemplo 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

Lidando com ValueErrors
Se você se deparar com uma situação em que fazer

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

Joga um

ValueError: Unknown string format

Isso significa que você tem valores inválidos (não coercíveis). Se concordar com a conversão deles para pd.NaT, você pode adicionar um errors='coerce'argumento para to_datetime:

df['time'] = pd.to_datetime(df['time'], errors='coerce')
Andy Hayden
fonte
Oi pessoal, @AndyHayden podem remover a parte do tempo da data? Eu não preciso dessa parte?
yoshiserry
No 0.13.1 dos pandas, as últimas 00: 00: 00s não são exibidas.
Andy Hayden
e nas outras versões, como os removemos / e ou não os exibimos?
yoshiserry
Não acho que isso possa ser feito de uma maneira agradável, há uma discussão para adicionar date_format como float_format (que você viu). Eu recomendo atualizar de qualquer maneira.
Andy Hayden
meu problema é que minha data está neste formato ... 41516.43 e recebo este erro. Eu esperaria que ele retornasse algo como 03/02/2014 na nova coluna ?! O ERRO: #convert valores de data na coluna "load_date" para datas budget_dataset ['date_last_load'] = pd.to_datetime (budget_dataset ['load_date']) budget_dataset -c: 2: SettingWithCopyWarning: Um valor está tentando ser definido em um cópia de uma fatia de um DataFrame. Tente usar .loc [row_index, col_indexer] = value em vez disso
yoshiserry
35

Imagino que muitos dados entrem no Pandas a partir de arquivos CSV; nesse caso, você pode simplesmente converter a data durante a leitura inicial do CSV:

dfcsv = pd.read_csv('xyz.csv', parse_dates=[0])onde o 0 se refere à coluna em que a data está.
Você também pode adicionar , index_col=0lá se quiser que a data seja o seu índice.

Veja https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

fantabolous
fonte
Obrigado, era exatamente disso que eu precisava. A documentação foi movida, porém, você pode encontrá-la aqui: pandas.pydata.org/pandas-docs/stable/reference/api/…
Sastibe
24

Agora você pode fazer df['column'].dt.date

Observe que, para objetos datetime, se você não vir a hora em que são todos 00:00:00, isso não é pandas. Esse é o notebook iPython tentando fazer as coisas parecerem bonitas.

Szeitlin
fonte
2
Este não funciona para mim, ele reclama: Só posso usar o acessador .dt com valores datetimelike
smishra
2
você pode ter que fazer df[col] = pd.to_datetime(df[col])primeiro para converter sua coluna em objetos de data e hora.
szeitlin
O problema com esta resposta é que ela converte a coluna dtype = objectque ocupa muito mais memória do que uma coluna verdadeira datetime dtypeem pandas.
elPastor
6

Outra maneira de fazer isso funciona bem se você tiver várias colunas para converter em data e hora.

cols = ['date1','date2']
df[cols] = df[cols].apply(pd.to_datetime)
SSS
fonte
Pergunta para data e não datetime.
Mark Andersen
@MarkAndersen contanto que você tenha dateapenas valores em suas colunas, a conversão para data e hora reterá apenas as informações pertinentes. Se você converter explicitamente usando df['datetime_col'].dt.dateisso resultará em um objectdtype; perda no gerenciamento de memória.
Sumanth Lazarus
5

Se você deseja obter o formato DATE e não DATETIME:

df["id_date"] = pd.to_datetime(df["id_date"]).dt.date
David Valenzuela Urrutia
fonte
1

Pode ser que as datas precisem ser convertidas para uma frequência diferente. Nesse caso, sugiro definir um índice por datas.

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

Depois disso, você pode converter mais facilmente para o tipo de formato de data de que mais precisa. Abaixo, eu converto sequencialmente para vários formatos de data, terminando com um conjunto de datas diárias no início do mês.

#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)

Para resumir, não mostro que executo o código a seguir após cada linha acima:

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

Isso me dá a seguinte saída:

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'>
Ted M.
fonte
0

Tente converter uma das linhas em carimbo de data / hora usando a função pd.to_datetime e, em seguida, use .map para mapear o formulário para a coluna inteira

Mwanaidi Nicole
fonte
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
fonte
0

Para ser mais completo, outra opção, que pode não ser a mais direta, um pouco semelhante à proposta por @SSS, mas usando a biblioteca datetime é:

import datetime
df["Date"] = df["Date"].apply(lambda x: datetime.datetime.strptime(x, '%Y-%d-%m').date())
rubebop
fonte