Combine colunas de data e hora usando python pandas

113

Eu tenho um dataframe do pandas com as seguintes colunas;

Date              Time
01-06-2013      23:00:00
02-06-2013      01:00:00
02-06-2013      21:00:00
02-06-2013      22:00:00
02-06-2013      23:00:00
03-06-2013      01:00:00
03-06-2013      21:00:00
03-06-2013      22:00:00
03-06-2013      23:00:00
04-06-2013      01:00:00

Como faço para combinar dados ['Data'] e dados ['Hora'] para obter o seguinte? Existe uma maneira de fazer usando pd.to_datetime?

Date
01-06-2013 23:00:00
02-06-2013 01:00:00
02-06-2013 21:00:00
02-06-2013 22:00:00
02-06-2013 23:00:00
03-06-2013 01:00:00
03-06-2013 21:00:00
03-06-2013 22:00:00
03-06-2013 23:00:00
04-06-2013 01:00:00
rico
fonte
Obrigado por todas as respostas. Eu tentei a maioria deles, mas ainda quando adiciono essas informações de data e hora como parte de um dataframe maior. A coluna datetime apenas exibe a data e as informações de hora não são exibidas. Devemos entender que o tempo está escondido ali ou é removido?
karthikeyan

Respostas:

169

Vale a pena mencionar que você pode ter conseguido ler isso diretamente, por exemplo, se estava read_csvusando parse_dates=[['Date', 'Time']].

Supondo que sejam apenas strings, você pode simplesmente adicioná-los (com um espaço), permitindo aplicar to_datetime:

In [11]: df['Date'] + ' ' + df['Time']
Out[11]:
0    01-06-2013 23:00:00
1    02-06-2013 01:00:00
2    02-06-2013 21:00:00
3    02-06-2013 22:00:00
4    02-06-2013 23:00:00
5    03-06-2013 01:00:00
6    03-06-2013 21:00:00
7    03-06-2013 22:00:00
8    03-06-2013 23:00:00
9    04-06-2013 01:00:00
dtype: object

In [12]: pd.to_datetime(df['Date'] + ' ' + df['Time'])
Out[12]:
0   2013-01-06 23:00:00
1   2013-02-06 01:00:00
2   2013-02-06 21:00:00
3   2013-02-06 22:00:00
4   2013-02-06 23:00:00
5   2013-03-06 01:00:00
6   2013-03-06 21:00:00
7   2013-03-06 22:00:00
8   2013-03-06 23:00:00
9   2013-04-06 01:00:00
dtype: datetime64[ns]

Nota: surpreendentemente (para mim), isso funciona bem com NaNs sendo convertidos para NaT, mas vale a pena se preocupar com a conversão (talvez usando o raiseargumento).

Andy Hayden
fonte
6
Não sabia sobre o recurso de combinação automática, e trabalha com várias entradas também, como: parse_dates=[['Start date', 'Start time'], ['End date', 'End time']]). Pandas <3
5agado
43

A resposta aceita funciona para colunas do tipo de dados string. Para completar: me deparei com esta questão ao pesquisar como fazer isso quando as colunas são de tipos de dados: data e hora.

df.apply(lambda r : pd.datetime.combine(r['date_column_name'],r['time_column_name']),1)
jka.ne
fonte
2
Não consigo encontrar nada sobre o tipo timed, nos pandas. Eu tenho um timedelta(e um datetime) caso em que você só precisa adicioná-los, veja minha resposta
toto_tico
Quando eu 'pd.read_excel' uma coluna do Excel que o Excel identifica como "Tempo", o pandas também a lê como "Tempo" automaticamente, sem qualquer argumento de análise necessário. Obrigado por esta solução. +1
Saeed
1
Apenas uma observação: a partir do pandas 1.0.0 se pd.datetime tornou obsoleto e é sugerido apenas importar explicitamente o datetimemódulo.
CopOnTheRun
16

Você pode usar isso para mesclar data e hora na mesma coluna do dataframe.

import pandas as pd    
data_file = 'data.csv' #path of your file

Lendo o arquivo .csv com colunas mescladas Date_Time:

data = pd.read_csv(data_file, parse_dates=[['Date', 'Time']]) 

Você pode usar esta linha para manter as outras colunas também.

data.set_index(['Date', 'Time'], drop=False)
MK Rana
fonte
1
Você também pode usar personalizado date_parser, por exemploparser = lambda date: pd.datetime.strptime(date, '%d-%b-%y %H:%M:%S')
Serendipity,
11

Você pode lançar as colunas se os tipos forem diferentes (datetime e timestamp ou str) e usar to_datetime:

df.loc[:,'Date'] = pd.to_datetime(df.Date.astype(str)+' '+df.Time.astype(str))

Resultado:

0   2013-01-06 23:00:00
1   2013-02-06 01:00:00
2   2013-02-06 21:00:00
3   2013-02-06 22:00:00
4   2013-02-06 23:00:00
5   2013-03-06 01:00:00
6   2013-03-06 21:00:00
7   2013-03-06 22:00:00
8   2013-03-06 23:00:00
9   2013-04-06 01:00:00

melhor,

Chris PERE
fonte
10

Não tenho reputação suficiente para comentar sobre jka.ne então:

Tive que alterar a linha de jka.ne para que funcionasse:

df.apply(lambda r : pd.datetime.combine(r['date_column_name'],r['time_column_name']).time(),1)

Isso pode ajudar outras pessoas.

Além disso, testei uma abordagem diferente, usando em replacevez de combine:

def combine_date_time(df, datecol, timecol):
    return df.apply(lambda row: row[datecol].replace(
                                hour=row[timecol].hour,
                                minute=row[timecol].minute),
                    axis=1)

que no caso do OP seria:

combine_date_time(df, 'Date', 'Time')

Cronometrei ambas as abordagens para um conjunto de dados relativamente grande (> 500.000 linhas) e ambas têm tempos de execução semelhantes, mas o uso combineé mais rápido (59s para replacevs 50s para combine).

jabellcu
fonte
5

A resposta realmente depende de quais são seus tipos de coluna . No meu caso, eu tinha datetimee timedelta.

> df[['Date','Time']].dtypes
Date     datetime64[ns]
Time    timedelta64[ns]

Se este for o seu caso, você só precisa adicionar as colunas:

> df['Date'] + df['Time']
toto_tico
fonte
A resposta aceita pressupõe cadeias de caracteres: "Supondo que sejam apenas cadeias de caracteres, você pode simplesmente adicioná-los (com um espaço)" . Minhas respostas são para datetimee timedelta. A resposta principal de alguma forma descobriu que as colunas eram strings, ou talvez fosse apenas a resposta que funcionou para aquele que postou a pergunta.
toto_tico
4

Você também pode converter para datetimesem concatenação de string, combinando datetimee timedeltaobjetos. Combinado com pd.DataFrame.pop, você pode remover a série de origem simultaneamente:

df['DateTime'] = pd.to_datetime(df.pop('Date')) + pd.to_timedelta(df.pop('Time'))

print(df)

             DateTime
0 2013-01-06 23:00:00
1 2013-02-06 01:00:00
2 2013-02-06 21:00:00
3 2013-02-06 22:00:00
4 2013-02-06 23:00:00
5 2013-03-06 01:00:00
6 2013-03-06 21:00:00
7 2013-03-06 22:00:00
8 2013-03-06 23:00:00
9 2013-04-06 01:00:00

print(df.dtypes)

DateTime    datetime64[ns]
dtype: object
jpp
fonte
1
Ótima solução geral! Eu tinha tipo datetime date e str time e isso funcionou.
pardal
3

Primeiro, certifique-se de ter os tipos de dados corretos:

df["Date"] = pd.to_datetime(df["Date"])
df["Time"] = pd.to_timedelta(df["Time"])

Então você os combina facilmente:

df["DateTime"] = df["Date"] + df["Time"]
queise
fonte
2

Use a combinefunção:

datetime.datetime.combine(date, time)
Stephen
fonte
2

Meu conjunto de dados tinha dados de resolução de 1 segundo por alguns dias e a análise pelos métodos sugeridos aqui era muito lenta. Em vez disso, usei:

dates = pandas.to_datetime(df.Date, cache=True)
times = pandas.to_timedelta(df.Time)
datetimes  = dates + times

Observe que o uso de cache=Truetorna a análise das datas muito eficiente, pois há apenas algumas datas exclusivas em meus arquivos, o que não é verdade para uma coluna combinada de data e hora.

tgbrooks
fonte
Isso é o que eu faria.
Yaakov Bressler
1

DADOS:

<TICKER>, <PER>, <DATE>, <TIME> , <OPEN>, <HIGH>, <LOW>, <CLOSE>, <VOL> SPFB.RTS, 1, 20190103,100100 , 106580.0000000,107260.0000000,106570.0000000 , 107230,0000000,3726

CÓDIGO:

data.columns = ['ticker', 'per', 'date', 'time', 'open', 'high', 'low', 'close', 'vol']    
data.datetime = pd.to_datetime(data.date.astype(str) + ' ' + data.time.astype(str), format='%Y%m%d %H%M%S')
hacknull
fonte