Je convertis un gros fichier texte en un stockage hdf dans l'espoir d'un accès plus rapide aux données. La conversion fonctionne très bien, mais la lecture du fichier csv ne se fait pas en parallèle. Il est vraiment lent (prend environ 30 minutes pour un fichier texte de 1 Go sur un SSD, donc je suppose qu'il n'est pas lié aux E/S).
Existe-t-il un moyen de le lire dans plusieurs threads en parallèle? Bien que cela puisse être important, je suis actuellement obligé d'exécuter sous Windows - juste au cas où cela ferait une différence.
from dask import dataframe as ddf
df = ddf.read_csv("data/Measurements*.csv",
sep=';',
parse_dates=["DATETIME"],
blocksize=1000000,
)
df.categorize([ 'Type',
'Condition',
])
df.to_hdf("data/data.hdf", "Measurements", 'w')
Oui, dask.dataframe peut lire en parallèle. Cependant, vous rencontrez deux problèmes:
Par défaut, dask.dataframe se parallélise avec les threads car la plupart des Pandas peuvent s'exécuter en parallèle dans plusieurs threads (libère le GIL). Pandas.read_csv est une exception, surtout si vos dataframes résultants utilisent des dtypes d'objet pour texte
L'écriture dans un seul fichier HDF forcera le calcul séquentiel (il est très difficile d'écrire dans un seul fichier en parallèle.)
Aujourd'hui, j'éviterais HDF et utiliserais plutôt Parquet. J'utiliserais probablement les programmateurs multiprocessing ou dask.distributed pour éviter les problèmes GIL sur une seule machine. La combinaison de ces deux devrait vous donner une mise à l'échelle linéaire complète.
from dask.distributed import Client
client = Client()
df = dask.dataframe.read_csv(...)
df.to_parquet(...)
Étant donné que votre ensemble de données tient probablement en mémoire, utilisez dask.dataframe.read_csv pour charger en parallèle avec plusieurs processus, puis passez immédiatement à Pandas.
import dask.dataframe as ddf
import dask.multiprocessing
df = ddf.read_csv("data/Measurements*.csv", # read in parallel
sep=';',
parse_dates=["DATETIME"],
blocksize=1000000,
)
df = df.compute(get=dask.multiprocessing.get) # convert to pandas
df['Type'] = df['Type'].astype('category')
df['Condition'] = df['Condition'].astype('category')
df.to_hdf('data/data.hdf', 'Measurements', format='table', mode='w')
En vous basant sur la réponse de @ MRocklin, dans les nouvelles versions de dask, vous pouvez utiliser df.compute(scheduler='processes')
ou df.compute(scheduler='threads')
pour convertir en pandas en utilisant le multitraitement ou le multithreading:
from dask import dataframe as ddf
df = ddf.read_csv("data/Measurements*.csv",
sep=';',
parse_dates=["DATETIME"],
blocksize=1000000,
)
df = df.compute(scheduler='processes') # convert to pandas
df['Type'] = df['Type'].astype('category')
df['Condition'] = df['Condition'].astype('category')
df.to_hdf('data/data.hdf', 'Measurements', format='table', mode='w')