Hub documentation

PyArrow

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

PyArrow

Arrow é um formato colunar e uma caixa de ferramentas para intercâmbio rápido de dados e análise em memória. Como o PyArrow suporta fsspec para ler e gravar dados remotos, você pode usar os caminhos do Hugging Face (hf://) para ler e gravar dados no Hub. Isso é especialmente útil para dados Parquet, já que o Parquet é o formato de arquivo mais comum no Hugging Face. De fato, o Parquet é particularmente eficiente graças à sua estrutura, tipagem, metadados e compressão.

Carregar uma Tabela

Você pode carregar dados de arquivos locais ou de armazenamento remoto, como o Hugging Face Datasets. O PyArrow suporta muitos formatos, incluindo CSV, JSON e, mais importante, Parquet:

>>> import pyarrow.parquet as pq
>>> table = pq.read_table("path/to/data.parquet")

Para carregar um arquivo do Hugging Face, o caminho precisa começar com hf://. Por exemplo, o caminho para o repositório do dataset stanfordnlp/imdb é hf://datasets/stanfordnlp/imdb. O dataset no Hugging Face contém múltiplos arquivos Parquet. O formato de arquivo Parquet foi projetado para tornar a leitura e a gravação de data frames eficientes e para facilitar o compartilhamento de dados entre linguagens de análise de dados. Veja como carregar o arquivo plain_text/train-00000-of-00001.parquet como uma Table do pyarrow (requer 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]]

Se você não quiser carregar os dados completos do Parquet, pode obter os metadados do Parquet ou carregar grupo de linhas por grupo de linhas:

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

Para mais informações sobre os caminhos do Hugging Face e como eles são implementados, consulte a documentação da biblioteca de cliente sobre o HfFileSystem.

Salvar uma Tabela

Você pode salvar uma tabela pyarrow usando pyarrow.parquet.write_table em um arquivo local ou diretamente no Hugging Face.

Para salvar a Tabela no Hugging Face, você primeiro precisa fazer login com sua conta do Hugging Face, por exemplo, usando:

hf auth login

Em seguida, você pode criar um repositório de dataset, por exemplo, usando:

from huggingface_hub import HfApi

HfApi().create_repo(repo_id="username/my_dataset", repo_type="dataset")

Por fim, você pode usar caminhos do Hugging Face no 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)

Observe que os arquivos Parquet no Hugging Face são otimizados para melhorar a eficiência de armazenamento, acelerar downloads e uploads e permitir streaming e edição eficientes de conjuntos de dados:

  • O Parquet Content Defined Chunking otimiza o Parquet para o Xet, o backend de armazenamento da Hugging Face. Ele acelera uploads e downloads graças à deduplicação baseada em chunks e permite a edição eficiente de arquivos
  • O índice de página acelera os filtros durante o streaming e permite acesso aleatório eficiente, por exemplo, no Dataset Viewer

PyArrow requer argumentos extras para gravar arquivos Parquet otimizados:

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

O chunking definido por conteúdo (CDC) faz com que o escritor Parquet agrupe as páginas de dados de forma que dados duplicados sejam agrupados e comprimidos de maneira idêntica. Sem o CDC, as páginas são agrupadas arbitrariamente e, portanto, os dados duplicados são impossíveis de detectar devido à compressão. Graças ao CDC, os uploads e downloads do Parquet no Hugging Face são mais rápidos, pois os dados duplicados são enviados ou baixados apenas uma vez.

Encontre mais informações sobre Xet aqui.

Aproveite a deduplicação do Xet para Parquet

Arquivos Parquet otimizados são gravados com Content Defined Chunking, o que permite a deduplicação. Isso acelera os uploads, pois blocos de dados que já existem no Hugging Face não precisam ser enviados novamente, o que economiza muito I/O.

Por exemplo, este código faz o upload do conteúdo de table e, em seguida, para edited_table, o upload é mais rápido, pois ele faz o upload apenas dos blocos que foram alterados:

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

Os chunks têm ~64kB e o Parquet salva os dados coluna por coluna, então, na prática, é o que acontece ao editar um arquivo Parquet Otimizado:

  • adicione uma nova coluna -> apenas os blocos da nova coluna são enviados
  • adicionar/editar/excluir uma linha -> um chunk por coluna é enviado

E, além disso, os blocos do rodapé do Parquet que contêm metadados também são enviados.

Use imagens

Você pode carregar uma pasta com um arquivo de metadados contendo um campo para os nomes ou caminhos das imagens, estruturado da seguinte forma:

Example 1:            Example 2:
folder/               folder/
├── metadata.parquet  ├── metadata.parquet
├── img000.png        └── images
├── img001.png            ├── img000.png
...                       ...
└── imgNNN.png            └── imgNNN.png

Você pode iterar nos caminhos das imagens da seguinte forma:

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
    ...

Como o conjunto de dados está em uma estrutura suportada (um arquivo metadata.parquet com um campo file_name), você pode salvar esse conjunto de dados no Hugging Face e o Dataset Viewer exibirá tanto os metadados quanto as imagens.

from huggingface_hub import HfApi
api = HfApi()

api.upload_folder(
    folder_path=folder_path,
    repo_id="username/my_image_dataset",
    repo_type="dataset",
)

Incorporar Imagens dentro de Parquet

O PyArrow possui um tipo binário que permite armazenar os bytes das imagens em tabelas Arrow. Dessa forma, é possível salvar o dataset como um único arquivo Parquet contendo tanto as imagens (bytes e caminho) quanto os metadados das amostras:

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)

Definir o tipo de imagem nos metadados do esquema Arrow permite que outras bibliotecas e o Visualizador de Conjuntos de Dados do Hugging Face saibam que “image” contém imagens e não apenas dados binários.

Use Áudios

Você pode carregar uma pasta com um arquivo de metadados contendo um campo para os nomes ou caminhos dos áudios, estruturado da seguinte forma:

Example 1:            Example 2:
folder/               folder/
├── metadata.parquet  ├── metadata.parquet
├── rec000.wav        └── audios
├── rec001.wav            ├── rec000.wav
...                       ...
└── recNNN.wav            └── recNNN.wav

Você pode iterar nos caminhos dos áudios da seguinte forma:

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
    ...

Como o conjunto de dados está em uma estrutura suportada (um arquivo metadata.parquet com um campo file_name), você pode salvá-lo no Hugging Face, e o Hub Dataset Viewer exibirá tanto os metadados quanto o áudio.

from huggingface_hub import HfApi
api = HfApi()

api.upload_folder(
    folder_path=folder_path,
    repo_id="username/my_audio_dataset",
    repo_type="dataset",
)

Incorporar áudio em Parquet

O PyArrow possui um tipo binário que permite armazenar bytes de áudio em tabelas Arrow. Dessa forma, é possível salvar o dataset como um único arquivo Parquet contendo tanto o áudio (bytes e caminho) quanto os metadados das amostras:

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)

Definir o tipo Audio nos metadados do esquema Arrow permite que outras bibliotecas e o Hugging Face Dataset Viewer reconheçam que “audio” contém dados de áudio, e não apenas dados binários.

Update on GitHub