Traitement de grands ensembles de données

Beginner

This tutorial is from open-source community. Access the source code

Introduction

Ce laboratoire se concentre sur la manière d'adapter l'analyse de données à des ensembles de données plus volumineux en utilisant pandas. Il couvre des méthodes telles que le chargement de moins de données, l'utilisation de types de données efficaces, le fractionnement (chunking) et l'utilisation d'autres bibliothèques comme Dask. Il est important de noter que pandas est plus adapté aux analyses en mémoire et peut ne pas être l'outil idéal pour les très grands ensembles de données.

Conseils pour la machine virtuelle (VM)

Une fois le démarrage de la machine virtuelle terminé, cliquez dans le coin supérieur gauche pour basculer vers l'onglet Notebook afin d'accéder à Jupyter Notebook pour pratiquer.

Parfois, vous devrez peut-être attendre quelques secondes que Jupyter Notebook ait terminé de charger. La validation des opérations ne peut pas être automatisée en raison des limitations de Jupyter Notebook.

Si vous rencontrez des problèmes lors de votre apprentissage, n'hésitez pas à demander de l'aide à Labby. Fournissez vos commentaires après la session, et nous résoudrons rapidement le problème pour vous.

Générer un ensemble de données

La première étape consiste à générer un grand ensemble de données pour les tests. Nous créons un ensemble de données avec de nombreuses colonnes qui peut être stocké dans un fichier parquet. Cette étape nécessite les bibliothèques pandas et numpy.

import pandas as pd
import numpy as np

def make_timeseries(start="2000-01-01", end="2000-12-31", freq="1D", seed=None):
    ## Fonction pour générer des données de séries temporelles
    index = pd.date_range(start=start, end=end, freq=freq, name="timestamp")
    n = len(index)
    state = np.random.RandomState(seed)
    columns = {
        "name": state.choice(["Alice", "Bob", "Charlie"], size=n),
        "id": state.poisson(1000, size=n),
        "x": state.rand(n) * 2 - 1,
        "y": state.rand(n) * 2 - 1,
    }
    df = pd.DataFrame(columns, index=index, columns=sorted(columns))
    if df.index[-1] == end:
        df = df.iloc[:-1]
    return df

timeseries = [
    make_timeseries(freq="1T", seed=i).rename(columns=lambda x: f"{x}_{i}")
    for i in range(10)
]
ts_wide = pd.concat(timeseries, axis=1)
ts_wide.to_parquet("timeseries_wide.parquet")

Charger moins de données

Au lieu de charger toutes les données, nous pouvons charger seulement les colonnes dont nous avons besoin. Ici, nous démontrons deux méthodes pour charger moins de données à partir du fichier parquet.

## Option 1: Charger toutes les données puis filtrer
columns = ["id_0", "name_0", "x_0", "y_0"]
pd.read_parquet("timeseries_wide.parquet")[columns]

## Option 2: Charger seulement les colonnes demandées
pd.read_parquet("timeseries_wide.parquet", columns=columns)

Utiliser des types de données efficaces

Les types de données par défaut de pandas ne sont pas les plus économes en mémoire. Cette étape montre comment utiliser des types de données plus efficaces pour stocker des ensembles de données plus volumineux en mémoire.

ts = make_timeseries(freq="30S", seed=0)
ts.to_parquet("timeseries.parquet")
ts = pd.read_parquet("timeseries.parquet")

## Convertir la colonne 'name' en type 'category' pour plus d'efficacité
ts2 = ts.copy()
ts2["name"] = ts2["name"].astype("category")

## Réduire les colonnes numériques aux types les plus petits possibles
ts2["id"] = pd.to_numeric(ts2["id"], downcast="unsigned")
ts2[["x", "y"]] = ts2[["x", "y"]].apply(pd.to_numeric, downcast="float")

Utiliser le fractionnement (chunking)

Le fractionnement (chunking) est une méthode consistant à diviser un grand problème en petits problèmes qui peuvent être résolus indépendamment. Tant que chaque fraction (chunk) rentre en mémoire, vous pouvez travailler avec des ensembles de données beaucoup plus volumineux que la mémoire disponible.

files = pathlib.Path("data/timeseries/").glob("ts*.parquet")
counts = pd.Series(dtype=int)
for path in files:
    df = pd.read_parquet(path)
    counts = counts.add(df["name"].value_counts(), fill_value=0)
counts.astype(int)

Utiliser d'autres bibliothèques

D'autres bibliothèques telles que Dask peuvent gérer des ensembles de données plus volumineux que la mémoire disponible. Dask propose une API similaire à celle de pandas et peut traiter les données en parallèle.

import dask.dataframe as dd

ddf = dd.read_parquet("data/timeseries/ts*.parquet", engine="pyarrow")

## Calculer les décomptes de valeurs à l'aide de Dask
ddf["name"].value_counts().compute()

Résumé

Dans ce laboratoire (lab), nous avons démontré différentes techniques pour adapter l'analyse de données à des ensembles de données plus volumineux en utilisant pandas. Nous avons généré un grand ensemble de données, appris à charger moins de données, à utiliser des types de données efficaces et le fractionnement (chunking). Nous avons également exploré comment tirer parti d'autres bibliothèques telles que Dask pour gérer des ensembles de données plus volumineux que la mémoire disponible. Les techniques et les concepts appris dans ce laboratoire seront utiles lors du traitement de grands ensembles de données dans les projets d'analyse de données.