Mantenha apenas parte da data ao usar pandas.to_datetime


201

Eu uso pandas.to_datetimepara analisar as datas nos meus dados. Por padrão, os pandas representam as datas datetime64[ns], embora as datas sejam apenas diárias. Gostaria de saber se existe uma maneira elegante / inteligente de converter as datas para datetime.dateou datetime64[D]para que, quando eu escrevo os dados em CSV, as datas não sejam anexadas 00:00:00. Eu sei que posso converter o tipo manualmente, elemento por elemento:

[dt.to_datetime().date() for dt in df.dates]

Mas isso é muito lento, pois tenho muitas linhas e meio que derrota o propósito de usar pandas.to_datetime. Existe uma maneira de converter a dtypecoluna inteira de uma só vez? Ou, como alternativa, pandas.to_datetimesuporta uma especificação de precisão para que eu possa me livrar da parte do tempo enquanto trabalho com dados diários?


2
Eu não sei um bom caminho, mas df.dates.apply(lambda x: x.date()) deve ser pelo menos um pouco mais rápido. também dê uma olhada em github.com/pydata/pandas/issues/2583
root


1
Eu consideraria essas duas perguntas como diferentes. A possível duplicata a que você se refere visa dividir a parte da data e a parte da hora de uma coluna de data e hora. Essa pergunta é motivada pela conversão de toda a coluna de uma só vez. Imagine que você tenha um quadro de dados com 20 colunas que representam datas. Você não deseja especificar quais colunas gravar no csv, conforme sugerido na outra pergunta.

1
No momento, não há suporte para isso (@root aponta para o possível aprimoramento), qual é o objetivo de fazer isso ao escrever para csv?
23413 Jeff Jeff

3
Bem, geralmente temos que gravar dados em arquivos csv para serem lidos por outros programas. As 00:00:00 redundantes apenas dificultam o processamento em geral, especialmente quando estou trabalhando com dados puramente diários.

Respostas:


286

Desde a versão, 0.15.0agora isso pode ser feito facilmente usando .dtpara acessar apenas o componente de data:

df['just_date'] = df['dates'].dt.date

O exemplo acima retorna um datetime.datedtype; se você deseja obter um datetime64, é possível apenas normalizeo componente de horário para meia-noite, para que ele defina todos os valores para 00:00:00:

df['normalised_date'] = df['dates'].dt.normalize()

Isso mantém o tipo, datetime64mas a tela mostra apenas o datevalor.


33

Solução Simples:

df['date_only'] = df['date_time_column'].dt.date

Apenas um aviso, isso altera o tipo para objeto. Portanto, você precisará digitar ('datetime64') para manter a consistência.
misantroop

25

Embora eu tenha votado positivamente na resposta de EdChum, que é a resposta mais direta à pergunta feita pelo OP, ele realmente não resolve o problema de desempenho (ainda depende de datetimeobjetos python e, portanto, qualquer operação neles não será vetorizada - ou seja, será lento).

Uma alternativa com melhor desempenho é usar df['dates'].dt.floor('d'). Estritamente falando, ele "não mantém apenas parte da data", pois apenas define a hora 00:00:00. Mas funciona como desejado pelo OP quando, por exemplo:

  • impressão em tela
  • salvando em csv
  • usando a coluna para groupby

... e é muito mais eficiente, pois a operação é vetorizada.

EDIT: na verdade, a resposta do OP teria preferido é, provavelmente, "versões recentes do pandasque não escrever o tempo para csv se é 00:00:00para todas as observações".


Infelizmente to_jsonainda escreve a íntegra 00:00:00.
19417 IanS

@IanS, você quer dizer quando usa date_format='iso'?! Por padrão, ele gera apenas segundos desde a época.
Pietro Battiston

Sim, foi o que eu quis dizer.
23917 IanS

Isso é mais rápido do que dt.normalize()em séries com mais de algumas centenas de elementos.
C8H10N4O2 21/07

16

Pandas DatetimeIndexe Seriestem um método chamado normalizeque faz exatamente o que você deseja.

Você pode ler mais sobre isso nesta resposta .

Pode ser usado como ser.dt.normalize()


15

Pandas v0.13 +: use to_csvcom o date_formatparâmetro

Evite, sempre que possível, converter sua datetime64[ns]série em uma objectsérie de tipos de datetime.dateobjetos. O último, geralmente construído usando pd.Series.dt.date, é armazenado como uma matriz de ponteiros e é ineficiente em relação a uma série pura baseada em NumPy.

Como sua preocupação é o formato ao gravar em CSV , use o date_formatparâmetro de to_csv. Por exemplo:

df.to_csv(filename, date_format='%Y-%m-%d')

Veja as strftimediretrizes do Python para convenções de formatação.


8

Esta é uma maneira simples de extrair a data:

import pandas as pd

d='2015-01-08 22:44:09' 
date=pd.to_datetime(d).date()
print(date)

O OP já está usando o método .date () em sua pergunta, portanto esta solução não responde à pergunta, mas achei útil ver um exemplo simples de como usar o método date () apenas como referência.
Nic Scozzaro

5

Convertendo para datetime64[D]:

df.dates.values.astype('M8[D]')

Embora a atribuição novamente a um col DataFrame o reverta para [ns].

Se você queria real datetime.date:

dt = pd.DatetimeIndex(df.dates)
dates = np.array([datetime.date(*date_tuple) for date_tuple in zip(dt.year, dt.month, dt.day)])

3
Se você estiver usando o tipo ('M8 [D]'), ele transformará os valores ausentes na data de origem, 1970-1-1. Provavelmente é melhor usar pandas.to_datetime () hoje em dia.
Stewbaca

1
Observe para qualquer pessoa que inclua rotineiramente o módulo datetime como dt, este snipet de resposta substituirá esse módulo! @ Dale-Jung, talvez pudesse mudar a linha para algo como dt_index
yeliabsalohcin

Eu também estou encontrando um problema no qual a próxima vez que eu tento e adicionar uma nova linha através do df.loc[date]método, as reverte índice de volta para um timestamp, ou seja, comparações posteriores não funcionam mais
yeliabsalohcin

3

Basta dar uma resposta mais atualizada caso alguém veja este post antigo.

Adicionar "utc = False" ao converter para datetime removerá o componente de fuso horário e manterá apenas a data no tipo de dados datetime64 [ns].

pd.to_datetime(df['Date'], utc=False)

Você poderá salvá-lo no Excel sem receber o erro "ValueError: O Excel não oferece suporte a horários com fusos horários. Verifique se o horário está inconsciente antes de gravar no Excel".

insira a descrição da imagem aqui


Por algum motivo, isso falha após a aplicação de qualquer função agregada à coluna.
RaphX

0

Queria poder alterar o tipo de um conjunto de colunas em um quadro de dados e remover o horário mantendo o dia. redondo (), piso (), teto () todo o trabalho

df[date_columns] = df[date_columns].apply(pd.to_datetime)
df[date_columns] = df[date_columns].apply(lambda t: t.dt.floor('d'))
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.