J'ai une base de données avec quelques (centaines de) millions de lignes. Et je veux convertir date/heure en horodatage efficacement. Comment puis-je le faire?
Mon échantillon df
:
df = pd.DataFrame(index=pd.DatetimeIndex(start=dt.datetime(2016,1,1,0,0,1),
end=dt.datetime(2016,1,2,0,0,1), freq='H'))\
.reset_index().rename(columns={'index':'datetime'})
df.head()
datetime
0 2016-01-01 00:00:01
1 2016-01-01 01:00:01
2 2016-01-01 02:00:01
3 2016-01-01 03:00:01
4 2016-01-01 04:00:01
Maintenant, je convertis date/heure en horodatage valeur par valeur avec .apply()
, mais cela prend beaucoup de temps (quelques heures) si j'ai quelques centaines de millions de lignes:
df['ts'] = df[['datetime']].apply(lambda x: x[0].timestamp(), axis=1).astype(int)
df.head()
datetime ts
0 2016-01-01 00:00:01 1451602801
1 2016-01-01 01:00:01 1451606401
2 2016-01-01 02:00:01 1451610001
3 2016-01-01 03:00:01 1451613601
4 2016-01-01 04:00:01 1451617201
Le résultat ci-dessus est ce que je veux.
Si j'essaie d'utiliser l'accesseur .dt
de pandas.Series
, le message d'erreur suivant s'affiche:
df['ts'] = df['datetime'].dt.timestamp
AttributeError: l'objet 'DatetimeProperties' n'a pas d'attribut 'horodatage'
Si j'essaie de créer par exemple. les parties de date de datetime avec l'accesseur .dt
, alors il est beaucoup plus rapide que d'utiliser .apply()
:
df['date'] = df['datetime'].dt.date
df.head()
datetime ts date
0 2016-01-01 00:00:01 1451602801 2016-01-01
1 2016-01-01 01:00:01 1451606401 2016-01-01
2 2016-01-01 02:00:01 1451610001 2016-01-01
3 2016-01-01 03:00:01 1451613601 2016-01-01
4 2016-01-01 04:00:01 1451617201 2016-01-01
Je veux quelque chose de similaire avec les horodatages ...
Mais je ne comprends pas vraiment la documentation officielle: elle parle de " Conversion en horodatages " mais je n'y vois aucun horodatage; il parle simplement de la conversion en date/heure avec pd.to_datetime()
mais pas en horodatage ...
Le constructeur pandas.Timestamp
ne fonctionne pas non plus (retourne avec l'erreur ci-dessous):
df['ts2'] = pd.Timestamp(df['datetime'])
TypeError: impossible de convertir une entrée en horodatage
pandas.Series.to_timestamp
fait aussi quelque chose de totalement différent de ce que je veux:
df['ts3'] = df['datetime'].to_timestamp
df.head()
datetime ts ts3
0 2016-01-01 00:00:01 1451602801 <bound method Series.to_timestamp of 0 2016...
1 2016-01-01 01:00:01 1451606401 <bound method Series.to_timestamp of 0 2016...
2 2016-01-01 02:00:01 1451610001 <bound method Series.to_timestamp of 0 2016...
3 2016-01-01 03:00:01 1451613601 <bound method Series.to_timestamp of 0 2016...
4 2016-01-01 04:00:01 1451617201 <bound method Series.to_timestamp of 0 2016...
Je vous remercie!!
Je pense que vous devez d'abord convertir numpy array
par values
et transiter en int64
- la sortie est en ns
, il est donc nécessaire de diviser par 10 ** 9
:
df['ts'] = df.datetime.values.astype(np.int64) // 10 ** 9
print (df)
datetime ts
0 2016-01-01 00:00:01 1451606401
1 2016-01-01 01:00:01 1451610001
2 2016-01-01 02:00:01 1451613601
3 2016-01-01 03:00:01 1451617201
4 2016-01-01 04:00:01 1451620801
5 2016-01-01 05:00:01 1451624401
6 2016-01-01 06:00:01 1451628001
7 2016-01-01 07:00:01 1451631601
8 2016-01-01 08:00:01 1451635201
9 2016-01-01 09:00:01 1451638801
10 2016-01-01 10:00:01 1451642401
11 2016-01-01 11:00:01 1451646001
12 2016-01-01 12:00:01 1451649601
13 2016-01-01 13:00:01 1451653201
14 2016-01-01 14:00:01 1451656801
15 2016-01-01 15:00:01 1451660401
16 2016-01-01 16:00:01 1451664001
17 2016-01-01 17:00:01 1451667601
18 2016-01-01 18:00:01 1451671201
19 2016-01-01 19:00:01 1451674801
20 2016-01-01 20:00:01 1451678401
21 2016-01-01 21:00:01 1451682001
22 2016-01-01 22:00:01 1451685601
23 2016-01-01 23:00:01 1451689201
24 2016-01-02 00:00:01 1451692801
to_timestamp
est utilisé pour convertir de période en index date/heure .
Si vous ne voulez pas utiliser numpy, vous pouvez utiliser des conversions de pandas purs.
df['ts'] = pd.to_timedelta(df['datetime'], unit='ns').dt.total_seconds().astype(int)
Il existe également une autre méthode pour ce faire, qui utilise l'attribut "caché" de DatetimeIndex
appelé asi8
, qui crée un horodatage entier.
pd.DatetimeIndex(df.datetime).asi8
Wes McKinney a suggéré cette question dans cette question de flux de pile liée de manière tangentielle liée ici