J'essaie de convertir une colonne de mon dataframe en datetime. Suite à la discussion ici https://github.com/dask/dask/issues/86 J'ai essayé le code suivant:
import dask.dataframe as dd
df['time'].map_partitions(pd.to_datetime, columns='time').compute()
Mais je reçois le message d'erreur suivant
ValueError: Metadata inference failed, please provide `meta` keyword
Que dois-je mettre exactement sous meta? dois-je mettre un dictionnaire de TOUTES les colonnes en df ou seulement de la colonne 'time'? et quel type dois-je mettre? J'ai essayé dtype et datetime64 mais aucun d'entre eux ne fonctionne jusqu'à présent.
Merci et j'apprécie vos conseils,
Mise à jour
Je vais inclure ici les nouveaux messages d'erreur:
1) Utilisation de l'horodatage
df['trd_exctn_dt'].map_partitions(pd.Timestamp).compute()
TypeError: Cannot convert input to Timestamp
2) Utilisation de datetime et meta
meta = ('time', pd.Timestamp)
df['time'].map_partitions(pd.to_datetime,meta=meta).compute()
TypeError: to_datetime() got an unexpected keyword argument 'meta'
3) Juste en utilisant l'heure de la date: reste bloqué à 2%
In [14]: df['trd_exctn_dt'].map_partitions(pd.to_datetime).compute()
[ ] | 2% Completed | 2min 20.3s
Aussi, je voudrais pouvoir spécifier le format de la date, comme je le ferais dans les pandas:
pd.to_datetime(df['time'], format = '%m%d%Y'
Mise à jour 2
Après la mise à jour vers Dask 0.11, je n'ai plus de problème avec le mot-clé meta. Pourtant, je ne peux pas dépasser 2% sur une trame de données de 2 Go.
df['trd_exctn_dt'].map_partitions(pd.to_datetime, meta=meta).compute()
[ ] | 2% Completed | 30min 45.7s
Mise à jour 3
a mieux fonctionné de cette façon:
def parse_dates(df):
return pd.to_datetime(df['time'], format = '%m/%d/%Y')
df.map_partitions(parse_dates, meta=meta)
Je ne sais pas si c'est la bonne approche ou non
astype
Vous pouvez utiliser la méthode astype
pour convertir le dtype d'une série en dtype NumPy
df.time.astype('M8[us]')
Il existe probablement un moyen de spécifier un Pandas également (modifications bienvenues)
Lorsque vous utilisez des méthodes de boîte noire comme map_partitions
, dask.dataframe doit connaître le type et les noms de la sortie. Il existe plusieurs façons de procéder répertoriées dans la docstring pour map_partitions
.
Vous pouvez fournir un objet Pandas vide avec le bon dtype et le bon nom
meta = pd.Series([], name='time', dtype=pd.Timestamp)
Ou vous pouvez fournir un Tuple de (name, dtype)
pour une série ou dict pour un DataFrame
meta = ('time', pd.Timestamp)
Alors tout devrait bien se passer
df.time.map_partitions(pd.to_datetime, meta=meta)
Si vous appelez map_partitions
on df
à la place, vous devrez alors fournir les dtypes pour tout. Ce n'est cependant pas le cas dans votre exemple.
Dask est également livré avec to_timedelta, cela devrait donc également fonctionner.
df['time']=dd.to_datetime(df.time,unit='ns')
Les valeurs que l'unité prend sont les mêmes que pd.to_timedelta dans les pandas. Cela peut être trouvé ici .
Je ne sais pas si c'est la bonne approche, mais le mappage de la colonne a fonctionné pour moi:
df['time'] = df['time'].map(lambda x: pd.to_datetime(x, errors='coerce'))
Cela a fonctionné pour moi
ddf["Date"] = ddf["Date"].map_partitions(pd.to_datetime,format='%d/%m/%Y',meta = ('datetime64[ns]'))
Si le datetime est dans un format non ISO alors map_partition
donne de meilleurs résultats:
import dask
import pandas as pd
from dask.distributed import Client
client = Client()
ddf = dask.datasets.timeseries()
ddf = ddf.assign(datetime=ddf.index.astype(object))
ddf = (ddf.assign(datetime_nonISO = ddf['datetime'].astype(str).str.split(' ')
.apply(lambda x: x[1]+' '+x[0], meta=('object')))
%%timeit
ddf.datetime = ddf.datetime.astype('M8[s]')
ddf.compute()
11,3 s ± 719 ms par boucle (moyenne ± écart standard de 7 passages, 1 boucle chacun)
ddf = dask.datasets.timeseries()
ddf = ddf.assign(datetime=ddf.index.astype(object))
ddf = (ddf.assign(datetime_nonISO = ddf['datetime'].astype(str).str.split(' ')
.apply(lambda x: x[1]+' '+x[0], meta=('object')))
%%timeit
ddf.datetime_nonISO = (ddf.datetime_nonISO.map_partitions(pd.to_datetime
, format='%H:%M:%S %Y-%m-%d', meta=('datetime64[s]')))
ddf.compute()
8,78 s ± 599 ms par boucle (écart moyen ± standard de 7 passages, 1 boucle chacun)
ddf = dask.datasets.timeseries()
ddf = ddf.assign(datetime=ddf.index.astype(object))
ddf = (ddf.assign(datetime_nonISO = ddf['datetime'].astype(str).str.split(' ')
.apply(lambda x: x[1]+' '+x[0], meta=('object')))
%%timeit
ddf.datetime_nonISO = ddf.datetime_nonISO.astype('M8[s]')
ddf.compute()
1 min 8 s ± 3,65 s par boucle (dév. Moyenne ± standard de 7 passages, 1 boucle chacun)