web-dev-qa-db-fra.com

dask dataframe comment convertir la colonne en to_datetime

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

12
dleal

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

Utilisez map_partitions et meta

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.

12
MRocklin

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 .

6
Arundathi

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

Cela a fonctionné pour moi

ddf["Date"] = ddf["Date"].map_partitions(pd.to_datetime,format='%d/%m/%Y',meta = ('datetime64[ns]'))

2
citynorman

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)

0
skibee