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?

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

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

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


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.


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)

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


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'>

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


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

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())
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.