Hub documentation
PyArrow
PyArrow
Arrow est un format de données en colonnes et une boîte à outils pour l’échange rapide de données et l’analyse en mémoire.
Comme PyArrow prend en charge fsspec pour lire et écrire des données distantes, vous pouvez utiliser les chemins Hugging Face (hf://) pour lire et écrire des données sur le Hub.
C’est particulièrement utile pour les données Parquet, car Parquet est le format de fichier le plus courant sur Hugging Face.
En effet, Parquet est particulièrement efficace grâce à sa structure, son typage, ses métadonnées et sa compression.
Charger un tableau
Vous pouvez charger des données depuis des fichiers locaux ou depuis un stockage distant comme Hugging Face Datasets. PyArrow prend en charge de nombreux formats, notamment CSV, JSON et, plus important encore, Parquet :
>>> import pyarrow.parquet as pq
>>> table = pq.read_table("path/to/data.parquet")Pour charger un fichier depuis Hugging Face, le chemin doit commencer par hf://. Par exemple, le chemin vers le dépôt de données stanfordnlp/imdb est hf://datasets/stanfordnlp/imdb. Le jeu de données sur Hugging Face contient plusieurs fichiers Parquet. Le format de fichier Parquet est conçu pour rendre la lecture et l'écriture de data frames efficaces, et pour faciliter le partage de données entre les langages d'analyse de données. Voici comment charger le fichier plain_text/train-00000-of-00001.parquet en tant que Table pyarrow (il nécessite pyarrow>=21.0) :
>>> import pyarrow.parquet as pq
>>> table = pq.read_table("hf://datasets/stanfordnlp/imdb/plain_text/train-00000-of-00001.parquet")
>>> table
pyarrow.Table
text: string
label: int64
----
text: [["I rented I AM CURIOUS-YELLOW from my video store because of all the controversy that surrounded it (... 1542 chars omitted)", ...],...,[..., "The story centers around Barry McKenzie who must go to England if he wishes to claim his inheritan (... 221 chars omitted)"]]
label: [[0,0,0,0,0,...,0,0,0,0,0],...,[1,1,1,1,1,...,1,1,1,1,1]]Si vous ne souhaitez pas charger les données Parquet complètes, vous pouvez obtenir les métadonnées Parquet ou charger groupe de lignes par groupe de lignes à la place :
>>> import pyarrow.parquet as pq
>>> pf = pq.ParquetFile("hf://datasets/stanfordnlp/imdb/plain_text/train-00000-of-00001.parquet")
>>> pf.metadata
<pyarrow._parquet.FileMetaData object at 0x1171b4090>
created_by: parquet-cpp-arrow version 12.0.0
num_columns: 2
num_rows: 25000
num_row_groups: 25
format_version: 2.6
serialized_size: 62036
>>> for i in pf.num_row_groups:
... table = pf.read_row_group(i)
... ...Pour plus d’informations sur les chemins Hugging Face et leur implémentation, veuillez consulter la documentation de la bibliothèque client sur HfFileSystem.
Enregistrer un Table
Vous pouvez enregistrer un tableau pyarrow à l'aide de pyarrow.parquet.write_table dans un fichier local ou directement sur Hugging Face.
Pour enregistrer le Table sur Hugging Face, vous devez d'abord vous connecter avec votre compte Hugging Face, par exemple en utilisant :
hf auth loginVous pouvez ensuite créer un dépôt de jeu de données, par exemple en utilisant :
from huggingface_hub import HfApi
HfApi().create_repo(repo_id="username/my_dataset", repo_type="dataset")Enfin, vous pouvez utiliser des chemins Hugging Face dans PyArrow :
import pyarrow.parquet as pq
pq.write_table(table, "hf://datasets/username/my_dataset/imdb.parquet", use_content_defined_chunking=True)
# or write in separate files if the dataset has train/validation/test splits
pq.write_table(table_train, "hf://datasets/username/my_dataset/train.parquet", use_content_defined_chunking=True)
pq.write_table(table_valid, "hf://datasets/username/my_dataset/validation.parquet", use_content_defined_chunking=True)
pq.write_table(table_test , "hf://datasets/username/my_dataset/test.parquet", use_content_defined_chunking=True)Notez que les fichiers Parquet sur Hugging Face sont optimisés pour améliorer l’efficacité du stockage, accélérer les téléchargements et les téléversements, et permettre un streaming et une édition efficaces des jeux de données :
- Parquet Content Defined Chunking optimise Parquet pour Xet, le backend de stockage de Hugging Face. Il accélère les téléversements et les téléchargements grâce à la déduplication par chunks et permet une édition efficace des fichiers
- L'index de page accélère les filtres lors du streaming et permet un accès aléatoire efficace, par exemple dans le Dataset Viewer
PyArrow nécessite des arguments supplémentaires pour écrire des fichiers Parquet optimisés :
import pyarrow.parquet as pq
pq.write_table(
table,
"hf://datasets/username/my_dataset/imdb.parquet",
# Optimize for Xet
use_content_defined_chunking=True,
write_page_index=True,
)use_content_defined_chunking=Truepour activer le Parquet Content Defined Chunking, pour la déduplication et l'édition (nécessitepyarrow>=21.0)write_page_index=Truepour inclure un index de pages dans les métadonnées Parquet, pour le streaming et l'accès aléatoire
Le découpage par contenu défini (CDC) permet à l’écriture Parquet de découper les pages de données de manière à ce que les données en double soient découpées et compressées de façon identique. Sans CDC, les pages sont découpées arbitrairement et les données en double sont donc impossibles à détecter en raison de la compression. Grâce au CDC, les téléversements et téléchargements Parquet depuis Hugging Face sont plus rapides, car les données en double ne sont téléversées ou téléchargées qu’une seule fois.
Retrouvez plus d'informations sur Xet ici.
Exploiter la déduplication Xet pour Parquet
Les fichiers Parquet optimisés sont écrits avec le Content Defined Chunking, ce qui permet la déduplication. Cela accélère les téléversements, car les blocs de données qui existent déjà sur Hugging Face n’ont pas besoin d’être téléversés à nouveau, ce qui économise beaucoup d’I/O.
Par exemple, ce code téléverse le contenu de table, puis pour edited_table, le téléversement est plus rapide car il ne téléverse que les blocs modifiés :
import pyarrow.parquet as pq
pq.write_table(
table,
"hf://datasets/username/my_dataset/imdb.parquet",
# Optimize for Xet
use_content_defined_chunking=True,
write_page_index=True,
)
edited_table = ... # e.g. with added/modified/removed rows or columns
pq.write_table(
edited_table,
"hf://datasets/username/my_dataset/imdb.parquet",
# Optimize for Xet
use_content_defined_chunking=True,
write_page_index=True,
)Les blocs font environ 64 Ko et Parquet enregistre les données colonne par colonne, donc en pratique, voici ce qui se produit lors de l'édition d'un fichier Parquet optimisé :
- ajouter une nouvelle colonne -> seuls les fragments de la nouvelle colonne sont téléversés
- ajouter/modifier/supprimer une ligne -> un chunk par colonne est téléversé
En plus de cela, les blocs du pied de page Parquet contenant les métadonnées sont également téléversés.
Utiliser des images
Vous pouvez charger un dossier avec un fichier de métadonnées contenant un champ pour les noms ou les chemins des images, structuré de la manière suivante :
Example 1: Example 2:
folder/ folder/
├── metadata.parquet ├── metadata.parquet
├── img000.png └── images
├── img001.png ├── img000.png
... ...
└── imgNNN.png └── imgNNN.pngVous pouvez itérer sur les chemins des images de cette manière :
from pathlib import Path
import pyarrow as pq
folder_path = Path("path/to/folder")
table = pq.read_table(folder_path + "metadata.parquet")
for file_name in table["file_name"].to_pylist():
image_path = folder_path / file_name
...Puisque le jeu de données est dans une structure prise en charge (un fichier metadata.parquet avec un champ file_name), vous pouvez enregistrer ce jeu de données sur Hugging Face et le Dataset Viewer affiche à la fois les métadonnées et les images.
from huggingface_hub import HfApi
api = HfApi()
api.upload_folder(
folder_path=folder_path,
repo_id="username/my_image_dataset",
repo_type="dataset",
)Intégrer des images dans Parquet
PyArrow dispose d'un type binaire qui permet de stocker les octets des images dans les tableaux Arrow. Il est donc possible d'enregistrer le jeu de données sous forme d'un seul fichier Parquet contenant à la fois les images (octets et chemin) et les métadonnées des échantillons :
import pyarrow as pa
import pyarrow.parquet as pq
# Embed the image bytes in Arrow
image_array = pa.array([
{
"bytes": (folder_path / file_name).read_bytes(),
"path": file_name,
}
for file_name in table["file_name"].to_pylist()
])
table.append_column("image", image_array)
# (Optional) Set the HF Image type for the Dataset Viewer and the `datasets` library
features = {"image": {"_type": "Image"}} # or using datasets.Features(...).to_dict()
schema_metadata = {"huggingface": {"dataset_info": {"features": features}}}
table = table.replace_schema_metadata(schema_metadata)
# Save to Parquet
# (Optional) with use_content_defined_chunking for faster uploads and downloads
pq.write_table(table, "data.parquet", use_content_defined_chunking=True)Définir le type Image dans les métadonnées du schéma Arrow permet aux autres bibliothèques et au Hugging Face Dataset Viewer de savoir que « image » contient des images et non simplement des données binaires.
Utiliser des Audios
Vous pouvez charger un dossier avec un fichier de métadonnées contenant un champ pour les noms ou les chemins des audios, structuré de la manière suivante :
Example 1: Example 2:
folder/ folder/
├── metadata.parquet ├── metadata.parquet
├── rec000.wav └── audios
├── rec001.wav ├── rec000.wav
... ...
└── recNNN.wav └── recNNN.wavVous pouvez itérer sur les chemins des audios de cette manière :
from pathlib import Path
import pyarrow as pq
folder_path = Path("path/to/folder")
table = pq.read_table(folder_path + "metadata.parquet")
for file_name in table["file_name"].to_pylist():
audio_path = folder_path / file_name
...Puisque le jeu de données est dans une structure prise en charge (un fichier metadata.parquet avec un champ file_name), vous pouvez l’enregistrer sur Hugging Face, et le Hub Dataset Viewer affiche à la fois les métadonnées et l’audio.
from huggingface_hub import HfApi
api = HfApi()
api.upload_folder(
folder_path=folder_path,
repo_id="username/my_audio_dataset",
repo_type="dataset",
)Intégrer l'audio dans Parquet
PyArrow dispose d'un type binaire qui permet d'inclure des octets audio dans les tableaux Arrow. Il est donc possible d'enregistrer le jeu de données sous forme d'un seul fichier Parquet contenant à la fois l'audio (octets et chemin) et les métadonnées des échantillons :
import pyarrow as pa
import pyarrow.parquet as pq
# Embed the audio bytes in Arrow
audio_array = pa.array([
{
"bytes": (folder_path / file_name).read_bytes(),
"path": file_name,
}
for file_name in table["file_name"].to_pylist()
])
table.append_column("audio", audio_array)
# (Optional) Set the HF Audio type for the Dataset Viewer and the `datasets` library
features = {"audio": {"_type": "Audio"}} # or using datasets.Features(...).to_dict()
schema_metadata = {"huggingface": {"dataset_info": {"features": features}}}
table = table.replace_schema_metadata(schema_metadata)
# Save to Parquet
# (Optional) with use_content_defined_chunking for faster uploads and downloads
pq.write_table(table, "data.parquet", use_content_defined_chunking=True)Définir le type Audio dans les métadonnées du schéma Arrow permet aux autres bibliothèques et au Hugging Face Dataset Viewer de reconnaître que « audio » contient des données audio, et non de simples données binaires.
Update on GitHub