# Processo

🤗 O Datasets oferece diversas ferramentas para modificar a estrutura e o conteúdo de um conjunto de dados. Essas ferramentas são importantes para organizar um conjunto de dados, criar colunas adicionais, converter entre recursos e formatos, e muito mais.

Este guia mostrará como:

- Reordene as linhas e divida o conjunto de dados.
- Renomear e remover colunas, e outras operações comuns de colunas.
- Aplique funções de processamento a cada exemplo em um conjunto de dados.
- Concatene conjuntos de dados.
- Aplicar uma transformação de formatação personalizada.
- Salve e exporte conjuntos de dados processados.

Para mais detalhes específicos sobre o processamento de outras modalidades de dataset, consulte o guia de processamento de dataset de áudio, o guia de processamento de dataset de imagem ou o guia de processamento de dataset de texto.

Os exemplos neste guia usam o conjunto de dados MRPC, mas sinta-se à vontade para carregar qualquer conjunto de dados de sua escolha e seguir o tutorial!

```py
>>> from datasets import load_dataset
>>> dataset = load_dataset("nyu-mll/glue", "mrpc", split="train")
```

> [!WARNING]
> Todos os métodos de processamento neste guia retornam um novo objeto [Dataset](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset). A modificação não é feita in-place. Tenha cuidado para não sobrescrever seu dataset anterior!

## Ordenar, embaralhar, selecionar, dividir e fragmentar

Existem várias funções para reorganizar a estrutura de um conjunto de dados. Essas funções são úteis para selecionar apenas as linhas desejadas, criar divisões de treino e teste, e dividir conjuntos de dados muito grandes em blocos menores.

### Ordenar

Use [sort()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.sort) para ordenar os valores da coluna de acordo com seus valores numéricos. A coluna fornecida deve ser compatível com NumPy.

```py
>>> dataset["label"][:10]
[1, 0, 1, 0, 1, 1, 0, 1, 0, 0]
>>> sorted_dataset = dataset.sort("label")
>>> sorted_dataset["label"][:10]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> sorted_dataset["label"][-10:]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
```

Por baixo dos panos, isso cria uma lista de índices ordenada de acordo com os valores da coluna. Esse mapeamento de índices é então usado para acessar as linhas corretas na tabela Arrow subjacente.

### Embaralhar

A função [shuffle()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.shuffle) reorganiza aleatoriamente os valores das colunas. Você pode especificar o parâmetro `generator` nesta função para usar um `numpy.random.Generator` diferente, caso queira ter mais controle sobre o algoritmo usado para embaralhar o conjunto de dados.

```py
>>> shuffled_dataset = sorted_dataset.shuffle(seed=42)
>>> shuffled_dataset["label"][:10]
[1, 1, 1, 0, 1, 1, 1, 1, 1, 0]
```

Shuffling pega a lista de índices `[0:len(my_dataset)]` e embaralha-a para criar um mapeamento de índices. No entanto, assim que seu [Dataset](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset) possui um mapeamento de índices, a velocidade pode ficar 10x mais lenta. Isso ocorre porque há uma etapa extra para obter o índice da linha a ser lido usando o mapeamento de índices e, mais importante, você não está mais lendo blocos contíguos de dados. Para restaurar a velocidade, você precisaria reescrever o conjunto de dados inteiro no seu disco novamente usando [Dataset.flatten_indices()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.flatten_indices), que remove o mapeamento de índices. Alternativamente, você pode alternar para um [IterableDataset](/docs/datasets/main/pt/package_reference/main_classes#datasets.IterableDataset) e aproveitar seu embaralhamento aproximado rápido [IterableDataset.shuffle()](/docs/datasets/main/pt/package_reference/main_classes#datasets.IterableDataset.shuffle):

```py
>>> iterable_dataset = dataset.to_iterable_dataset(num_shards=128)
>>> shuffled_iterable_dataset = iterable_dataset.shuffle(seed=42, buffer_size=1000)
```

### Selecionar e filtrar

Há duas opções para filtrar linhas em um dataset: [select()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.select) e [filter()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.filter).

- [select()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.select) retorna linhas de acordo com uma lista de índices:

```py
>>> small_dataset = dataset.select([0, 10, 20, 30, 40, 50])
>>> len(small_dataset)
6
```

- [filter()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.filter) retorna as linhas que correspondem a uma condição especificada:

```py
>>> start_with_ar = dataset.filter(lambda example: example["sentence1"].startswith("Ar"))
>>> len(start_with_ar)
6
>>> start_with_ar["sentence1"]
['Around 0335 GMT , Tab shares were up 19 cents , or 4.4 % , at A $ 4.56 , having earlier set a record high of A $ 4.57 .',
'Arison said Mann may have been one of the pioneers of the world music movement and he had a deep love of Brazilian music .',
'Arts helped coach the youth on an eighth-grade football team at Lombardi Middle School in Green Bay .',
'Around 9 : 00 a.m. EDT ( 1300 GMT ) , the euro was at $ 1.1566 against the dollar , up 0.07 percent on the day .',
"Arguing that the case was an isolated example , Canada has threatened a trade backlash if Tokyo 's ban is not justified on scientific grounds .",
'Artists are worried the plan would harm those who need help most - performers who have a difficult time lining up shows .'
]
```

[filter()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.filter) também pode filtrar por índices se você definir `with_indices=True`:

```py
>>> even_dataset = dataset.filter(lambda example, idx: idx % 2 == 0, with_indices=True)
>>> len(even_dataset)
1834
>>> len(dataset) / 2
1834.0
```

A menos que a lista de índices a serem mantidos seja contígua, esses métodos também criam um mapeamento de índices por baixo dos panos.

### Dividir

A função [train_test_split()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.train_test_split) cria as partições de treino e teste caso seu conjunto de dados ainda não as possua. Isso permite ajustar as proporções relativas ou o número absoluto de amostras em cada partição. No exemplo abaixo, use o parâmetro `test_size` para criar uma partição de teste que corresponda a 10% do conjunto de dados original:

```py
>>> dataset.train_test_split(test_size=0.1)
{'train': Dataset(schema: {'sentence1': 'string', 'sentence2': 'string', 'label': 'int64', 'idx': 'int32'}, num_rows: 3301),
'test': Dataset(schema: {'sentence1': 'string', 'sentence2': 'string', 'label': 'int64', 'idx': 'int32'}, num_rows: 367)}
>>> 0.1 * len(dataset)
366.8
```

Os splits são embaralhados por padrão, mas você pode definir `shuffle=False` para evitar o embaralhamento.

### Shard

🤗 O Datasets oferece suporte a sharding para dividir um conjunto de dados muito grande em um número predefinido de blocos. Especifique o parâmetro `num_shards` em [shard()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.shard) para determinar o número de shards em que o conjunto de dados será dividido. Você também precisará fornecer o shard que deseja retornar com o parâmetro `index`.

Por exemplo, o conjunto de dados [stanfordnlp/imdb](https://huggingface.co/datasets/stanfordnlp/imdb) tem 25000 exemplos:

```py
>>> from datasets import load_dataset
>>> dataset = load_dataset("stanfordnlp/imdb", split="train")
>>> print(dataset)
Dataset({
    features: ['text', 'label'],
    num_rows: 25000
})
```

Após dividir o conjunto de dados em quatro fragmentos, o primeiro fragmento terá apenas 6250 exemplos:

```py
>>> dataset.shard(num_shards=4, index=0)
Dataset({
    features: ['text', 'label'],
    num_rows: 6250
})
>>> print(25000/4)
6250.0
```

## Renomear, remover, converter e achatar

As funções a seguir permitem modificar as colunas de um conjunto de dados. Essas funções são úteis para renomear ou remover colunas, alterar colunas para um novo conjunto de recursos e aplanar estruturas de colunas aninhadas.

### Renomear

Use [rename_column()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.rename_column) quando precisar renomear uma coluna no seu dataset. Os recursos associados à coluna original são, na verdade, movidos para o novo nome da coluna, em vez de apenas substituir a coluna original no local.

Forneça [rename_column()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.rename_column) com o nome da coluna original e o novo nome da coluna:

```py
>>> dataset
Dataset({
    features: ['sentence1', 'sentence2', 'label', 'idx'],
    num_rows: 3668
})
>>> dataset = dataset.rename_column("sentence1", "sentenceA")
>>> dataset = dataset.rename_column("sentence2", "sentenceB")
>>> dataset
Dataset({
    features: ['sentenceA', 'sentenceB', 'label', 'idx'],
    num_rows: 3668
})
```

### Remover

Quando você precisa remover uma ou mais colunas, forneça o nome da coluna a ser removida para a função [remove_columns()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.remove_columns). Remova mais de uma coluna fornecendo uma lista de nomes de colunas:

```py
>>> dataset = dataset.remove_columns("label")
>>> dataset
Dataset({
    features: ['sentence1', 'sentence2', 'idx'],
    num_rows: 3668
})
>>> dataset = dataset.remove_columns(["sentence1", "sentence2"])
>>> dataset
Dataset({
    features: ['idx'],
    num_rows: 3668
})
```

Por outro lado, [select_columns()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.select_columns) seleciona uma ou mais colunas para manter e remove as demais. Esta função aceita um nome de coluna ou uma lista de nomes de colunas:

```py
>>> dataset
Dataset({
    features: ['sentence1', 'sentence2', 'label', 'idx'],
    num_rows: 3668
})
>>> dataset = dataset.select_columns(['sentence1', 'sentence2', 'idx'])
>>> dataset
Dataset({
    features: ['sentence1', 'sentence2', 'idx'],
    num_rows: 3668
})
>>> dataset = dataset.select_columns('idx')
>>> dataset
Dataset({
    features: ['idx'],
    num_rows: 3668
})
```

### Cast

A função [cast()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.cast) transforma o tipo de recurso de uma ou mais colunas. Esta função aceita seus novos [Features](/docs/datasets/main/pt/package_reference/main_classes#datasets.Features) como argumento. O exemplo abaixo demonstra como alterar os recursos [ClassLabel](/docs/datasets/main/pt/package_reference/main_classes#datasets.ClassLabel) e [Value](/docs/datasets/main/pt/package_reference/main_classes#datasets.Value):

```py
>>> dataset.features
{'sentence1': Value('string'),
'sentence2': Value('string'),
'label': ClassLabel(names=['not_equivalent', 'equivalent']),
'idx': Value('int32')}

>>> from datasets import ClassLabel, Value
>>> new_features = dataset.features.copy()
>>> new_features["label"] = ClassLabel(names=["negative", "positive"])
>>> new_features["idx"] = Value("int64")
>>> dataset = dataset.cast(new_features)
>>> dataset.features
{'sentence1': Value('string'),
'sentence2': Value('string'),
'label': ClassLabel(names=['negative', 'positive']),
'idx': Value('int64')}
```

> [!TIP]
> O casting só funciona se o tipo de feature original e o novo tipo de feature forem compatíveis. Por exemplo, você pode fazer o casting de uma coluna com o tipo de feature `Value("int32")` para `Value("bool")` se a coluna original contiver apenas uns e zeros.

Use a função [cast_column()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.cast_column) para alterar o tipo de recurso de uma única coluna. Passe o nome da coluna e seu novo tipo de recurso como argumentos:

```py
>>> dataset.features
{'audio': Audio(sampling_rate=44100, mono=True)}

>>> dataset = dataset.cast_column("audio", Audio(sampling_rate=16000))
>>> dataset.features
{'audio': Audio(sampling_rate=16000, mono=True)}
```

### Achatar

Às vezes, uma coluna pode ser uma estrutura aninhada de vários tipos. Observe a estrutura aninhada abaixo do conjunto de dados SQuAD:

```py
>>> from datasets import load_dataset
>>> dataset = load_dataset("rajpurkar/squad", split="train")
>>> dataset.features
{'id': Value('string'),
 'title': Value('string'),
 'context': Value('string'),
 'question': Value('string'),
 'answers': {'text': List(Value('string')),
  'answer_start': List(Value('int32'))}}
```

O campo `answers` contém dois subcampos: `text` e `answer_start`. Use a função [flatten()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.flatten) para extrair os subcampos em colunas separadas:

```py
>>> flat_dataset = dataset.flatten()
>>> flat_dataset
Dataset({
    features: ['id', 'title', 'context', 'question', 'answers.text', 'answers.answer_start'],
 num_rows: 87599
})
```

Observe como os subcampos agora são colunas independentes: `answers.text` e `answers.answer_start`.

## Map

Algumas das aplicações mais poderosas do 🤗 Datasets vêm do uso da função [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map). O objetivo principal do [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) é acelerar as funções de processamento. Ele permite aplicar uma função de processamento a cada exemplo de um conjunto de dados, de forma independente ou em lotes. Essa função pode até criar novas linhas e colunas.

No exemplo a seguir, prefixe cada valor de `sentence1` no conjunto de dados com `'My sentence: '`.

Comece criando uma função que adiciona `'My sentence: '` ao início de cada frase. A função precisa aceitar e retornar um `dict`:

```py
>>> def add_prefix(example):
...     example["sentence1"] = 'My sentence: ' + example["sentence1"]
...     return example
```

Agora use [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) para aplicar a função `add_prefix` ao conjunto de dados inteiro:

```py
>>> updated_dataset = small_dataset.map(add_prefix)
>>> updated_dataset["sentence1"][:5]
['My sentence: Amrozi accused his brother , whom he called " the witness " , of deliberately distorting his evidence .',
"My sentence: Yucaipa owned Dominick 's before selling the chain to Safeway in 1998 for $ 2.5 billion .",
'My sentence: They had published an advertisement on the Internet on June 10 , offering the cargo for sale , he added .',
'My sentence: Around 0335 GMT , Tab shares were up 19 cents , or 4.4 % , at A $ 4.56 , having earlier set a record high of A $ 4.57 .',
]
```

Vamos examinar outro exemplo, mas desta vez você removerá uma coluna com [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map). Ao remover uma coluna, ela só é removida depois que o exemplo tiver sido fornecido à função mapeada. Isso permite que a função mapeada utilize o conteúdo das colunas antes que sejam removidas.

Especifique a coluna a ser removida com o parâmetro `remove_columns` em [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map):

```py
>>> updated_dataset = dataset.map(lambda example: {"new_sentence": example["sentence1"]}, remove_columns=["sentence1"])
>>> updated_dataset.column_names
['sentence2', 'label', 'idx', 'new_sentence']
```

> [!TIP]
> 🤗 O Datasets também possui uma função [remove_columns()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.remove_columns) que é mais rápida porque não copia os dados das colunas restantes.

Você também pode usar [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) com índices se definir `with_indices=True`. O exemplo abaixo adiciona o índice ao início de cada frase:

```py
>>> updated_dataset = dataset.map(lambda example, idx: {"sentence2": f"{idx}: " + example["sentence2"]}, with_indices=True)
>>> updated_dataset["sentence2"][:5]
['0: Referring to him as only " the witness " , Amrozi accused his brother of deliberately distorting his evidence .',
 "1: Yucaipa bought Dominick 's in 1995 for $ 693 million and sold it to Safeway for $ 1.8 billion in 1998 .",
 "2: On June 10 , the ship 's owners had published an advertisement on the Internet , offering the explosives for sale .",
 '3: Tab shares jumped 20 cents , or 4.6 % , to set a record closing high at A $ 4.57 .',
 '4: PG & E Corp. shares jumped $ 1.63 or 8 percent to $ 21.03 on the New York Stock Exchange on Friday .'
]
```

### Multiprocessamento

O multiprocessing acelera significativamente o processamento ao paralelizar processos na CPU. Defina o parâmetro `num_proc` em [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) para definir o número de processos a serem usados:

```py
>>> updated_dataset = dataset.map(lambda example, idx: {"sentence2": f"{idx}: " + example["sentence2"]}, with_indices=True, num_proc=4)
```

O [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) também funciona com o rank do processo se você definir `with_rank=True`. Isso é análogo ao parâmetro `with_indices`. O parâmetro `with_rank` na função mapeada vem depois do `index`, se este já estiver presente.

```py
>>> import torch
>>> from multiprocess import set_start_method
>>> from transformers import AutoTokenizer, AutoModelForCausalLM
>>> from datasets import load_dataset
>>>
>>> # Get an example dataset
>>> dataset = load_dataset("fka/awesome-chatgpt-prompts", split="train")
>>>
>>> # Get an example model and its tokenizer
>>> model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B-Chat").eval()
>>> tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B-Chat")
>>>
>>> def gpu_computation(batch, rank):
...     # Move the model on the right GPU if it's not there already
...     device = f"cuda:{(rank or 0) % torch.cuda.device_count()}"
...     model.to(device)
...
...     # Your big GPU call goes here, for example:
...     chats = [[
...         {"role": "system", "content": "You are a helpful assistant."},
...         {"role": "user", "content": prompt}
...     ] for prompt in batch["prompt"]]
...     texts = [tokenizer.apply_chat_template(
...         chat,
...         tokenize=False,
...         add_generation_prompt=True
...     ) for chat in chats]
...     model_inputs = tokenizer(texts, padding=True, return_tensors="pt").to(device)
...     with torch.no_grad():
...         outputs = model.generate(**model_inputs, max_new_tokens=512)
...     batch["output"] = tokenizer.batch_decode(outputs, skip_special_tokens=True)
...     return batch
>>>
>>> if __name__ == "__main__":
...     set_start_method("spawn")
...     updated_dataset = dataset.map(
...         gpu_computation,
...         batched=True,
...         batch_size=16,
...         with_rank=True,
...         num_proc=torch.cuda.device_count(),  # one process per GPU
...     )
```

O principal caso de uso de rank é paralelizar a computação entre várias GPUs. Isso requer definir `multiprocess.set_start_method("spawn")`. Caso contrário, você receberá o seguinte erro de CUDA:

```bash
RuntimeError: Cannot re-initialize CUDA in forked subprocess. To use CUDA with multiprocessing, you must use the 'spawn' start method.
```

### Processamento em lote

A função [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) suporta o trabalho com lotes de exemplos. Opere sobre lotes definindo `batched=True`. O tamanho padrão do lote é 1000, mas você pode ajustá-lo com o parâmetro `batch_size`. O processamento em lote permite aplicações interessantes, como dividir frases longas em trechos menores e aumentar os dados.

#### Dividir exemplos longos

Quando os exemplos são longos demais, você pode querer dividi-los em vários blocos menores. Comece criando uma função que:

1. Divide o campo `sentence1` em blocos de 50 caracteres.

2. Empilha todos os blocos para criar o novo conjunto de dados.

```py
>>> def chunk_examples(examples):
...     chunks = []
...     for sentence in examples["sentence1"]:
...         chunks += [sentence[i:i + 50] for i in range(0, len(sentence), 50)]
...     return {"chunks": chunks}
```

Aplique a função com [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map):

```py
>>> chunked_dataset = dataset.map(chunk_examples, batched=True, remove_columns=dataset.column_names)
>>> chunked_dataset[:10]
{'chunks': ['Amrozi accused his brother , whom he called " the ',
            'witness " , of deliberately distorting his evidenc',
            'e .',
            "Yucaipa owned Dominick 's before selling the chain",
            ' to Safeway in 1998 for $ 2.5 billion .',
            'They had published an advertisement on the Interne',
            't on June 10 , offering the cargo for sale , he ad',
            'ded .',
            'Around 0335 GMT , Tab shares were up 19 cents , or',
            ' 4.4 % , at A $ 4.56 , having earlier set a record']}
```

Observe como as frases agora são divididas em trechos mais curtos e há mais linhas no conjunto de dados.

```py
>>> dataset
Dataset({
 features: ['sentence1', 'sentence2', 'label', 'idx'],
 num_rows: 3668
})
>>> chunked_dataset
Dataset({
    features: ['chunks'],
    num_rows: 10470
})
```

#### Aumento de dados

A função [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) também pode ser usada para aumento de dados. O exemplo a seguir gera palavras adicionais para um token mascarado em uma frase.

Carregue e use o modelo [RoBERTa](https://huggingface.co/roberta-base) no [FillMaskPipeline](https://huggingface.co/transformers/main_classes/pipelines#transformers.FillMaskPipeline) do 🤗 Transformers:

```py
>>> from random import randint
>>> from transformers import pipeline

>>> fillmask = pipeline("fill-mask", model="roberta-base")
>>> mask_token = fillmask.tokenizer.mask_token
>>> smaller_dataset = dataset.filter(lambda e, i: i<100, with_indices=True)
```

Crie uma função para selecionar aleatoriamente uma palavra para mascarar na frase. A função também deve retornar a frase original e as duas principais substituições geradas pelo RoBERTA.

```py
>>> def augment_data(examples):
...     outputs = []
...     for sentence in examples["sentence1"]:
...         words = sentence.split(' ')
...         K = randint(1, len(words)-1)
...         masked_sentence = " ".join(words[:K]  + [mask_token] + words[K+1:])
...         predictions = fillmask(masked_sentence)
...         augmented_sequences = [predictions[i]["sequence"] for i in range(3)]
...         outputs += [sentence] + augmented_sequences
...
...     return {"data": outputs}
```

Use [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) para aplicar a função em todo o conjunto de dados:

```py
>>> augmented_dataset = smaller_dataset.map(augment_data, batched=True, remove_columns=dataset.column_names, batch_size=8)
>>> augmented_dataset[:9]["data"]
['Amrozi accused his brother , whom he called " the witness " , of deliberately distorting his evidence .',
 'Amrozi accused his brother, whom he called " the witness ", of deliberately withholding his evidence.',
 'Amrozi accused his brother, whom he called " the witness ", of deliberately suppressing his evidence.',
 'Amrozi accused his brother, whom he called " the witness ", of deliberately destroying his evidence.',
 "Yucaipa owned Dominick 's before selling the chain to Safeway in 1998 for $ 2.5 billion .",
 'Yucaipa owned Dominick Stores before selling the chain to Safeway in 1998 for $ 2.5 billion.',
 "Yucaipa owned Dominick's before selling the chain to Safeway in 1998 for $ 2.5 billion.",
 'Yucaipa owned Dominick Pizza before selling the chain to Safeway in 1998 for $ 2.5 billion.'
]
```

Para cada frase original, o RoBERTA aumentou uma palavra aleatória com três alternativas. A palavra original `distorting` é complementada por `withholding`, `suppressing` e `destroying`.

### Processamento assíncrono

Funções assíncronas são úteis para chamar endpoints de API em paralelo, por exemplo, para baixar conteúdo como imagens ou chamar um endpoint de modelo.

Você pode definir uma função assíncrona usando as palavras-chave `async` e `await`. Aqui está um exemplo de função para chamar um modelo de chat do Hugging Face:

```python
>>> import aiohttp
>>> import asyncio
>>> from huggingface_hub import get_token
>>> sem = asyncio.Semaphore(20)  # max number of simultaneous queries
>>> async def query_model(model, prompt):
...     api_url = f"https://api-inference.huggingface.co/models/{model}/v1/chat/completions"
...     headers = {"Authorization": f"Bearer {get_token()}", "Content-Type": "application/json"}
...     json = {"messages": [{"role": "user", "content": prompt}], "max_tokens": 20, "seed": 42}
...     async with sem, aiohttp.ClientSession() as session, session.post(api_url, headers=headers, json=json) as response:
...         output = await response.json()
...         return {"Output": output["choices"][0]["message"]["content"]}
```

Funções assíncronas são executadas em paralelo, o que acelera muito o processo. O mesmo código leva muito mais tempo se for executado sequencialmente, pois não faz nada enquanto aguarda a resposta do modelo. Em geral, recomenda-se usar `async` / `await` quando a sua função precisa aguardar uma resposta de uma API, por exemplo, ou se ela baixa dados e isso pode levar algum tempo.

Observe a presença de um `Semaphore`: ele define o número máximo de consultas que podem ser executadas em paralelo. É recomendável usar um `Semaphore` ao chamar APIs para evitar erros de limite de taxa.

Vamos usá-lo para chamar o modelo [microsoft/Phi-3-mini-4k-instruct](https://huggingface.co/microsoft/Phi-3-mini-4k-instruct) e pedir que ele retorne o tópico principal de cada problema de matemática no dataset [Maxwell-Jia/AIME_2024](https://huggingface.co/Maxwell-Jia/AIME_2024):

````python
>>> from datasets import load_dataset
>>> ds = load_dataset("Maxwell-Jia/AIME_2024", split="train")
>>> model = "microsoft/Phi-3-mini-4k-instruct"
>>> prompt = 'What is this text mainly about ? Here is the text:\n\n```\n{Problem}\n```\n\nReply using one or two words max, e.g. "The main topic is Linear Algebra".'
>>> async def get_topic(example):
...     return await query_model(model, prompt.format(Problem=example['Problem']))
>>> ds = ds.map(get_topic)
>>> ds[0]
{'ID': '2024-II-4',
 'Problem': 'Let $x,y$ and $z$ be positive real numbers that...',
 'Solution': 'Denote $\\log_2(x) = a$, $\\log_2(y) = b$, and...,
 'Answer': 33,
 'Output': 'The main topic is Logarithms.'}
````

Aqui, [Dataset.map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) executa a função `get_topic` de forma assíncrona, de modo que não precisa esperar por cada resposta individual do modelo, o que levaria muito tempo se fosse feito sequencialmente.

Por padrão, [Dataset.map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) executa até mil funções de mapeamento em paralelo, então não se esqueça de definir o número máximo de chamadas de API que podem ser executadas em paralelo com um `Semaphore`, caso contrário o modelo pode retornar erros de limite de taxa ou sobrecarga. Para casos de uso avançados, você pode alterar o número máximo de consultas em paralelo em `datasets.config`.

### Processar vários splits

Muitos conjuntos de dados possuem divisões que podem ser processadas simultaneamente com [DatasetDict.map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.DatasetDict.map). Por exemplo, tokenizar o campo `sentence1` nas divisões de treino e teste por:

```py
>>> from datasets import load_dataset

# load all the splits
>>> dataset = load_dataset('nyu-mll/glue', 'mrpc')
>>> encoded_dataset = dataset.map(lambda examples: tokenizer(examples["sentence1"]), batched=True)
>>> encoded_dataset["train"][0]
{'sentence1': 'Amrozi accused his brother , whom he called " the witness " , of deliberately distorting his evidence .',
'sentence2': 'Referring to him as only " the witness " , Amrozi accused his brother of deliberately distorting his evidence .',
'label': 1,
'idx': 0,
'input_ids': [  101,  7277,  2180,  5303,  4806,  1117,  1711,   117,  2292, 1119,  1270,   107,  1103,  7737,   107,   117,  1104,  9938, 4267, 12223, 21811,  1117,  2554,   119,   102],
'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
}
```

### Uso distribuído

Ao usar [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) em um ambiente distribuído, você também deve usar [torch.distributed.barrier](https://pytorch.org/docs/stable/distributed?highlight=barrier#torch.distributed.barrier). Isso garante que o processo principal execute o mapeamento, enquanto os outros processos carregam os resultados, evitando assim trabalho duplicado.

O exemplo a seguir mostra como você pode usar `torch.distributed.barrier` para sincronizar os processos:

```py
>>> from datasets import Dataset
>>> import torch.distributed

>>> dataset1 = Dataset.from_dict({"a": [0, 1, 2]})

>>> if training_args.local_rank > 0:
...     print("Waiting for main process to perform the mapping")
...     torch.distributed.barrier()

>>> dataset2 = dataset1.map(lambda x: {"a": x["a"] + 1})

>>> if training_args.local_rank == 0:
...     print("Loading results from main process")
...     torch.distributed.barrier()
```

## Lote

O método `batch()` permite agrupar amostras do conjunto de dados em lotes. Isso é particularmente útil quando você deseja criar lotes de dados para treinamento ou avaliação, especialmente ao trabalhar com modelos de aprendizado profundo.

Aqui está um exemplo de como usar o método `batch()`:

```python
>>> from datasets import load_dataset
>>> dataset = load_dataset("cornell-movie-review-data/rotten_tomatoes", split="train")
>>> batched_dataset = dataset.batch(batch_size=4)
>>> batched_dataset[0]
{'text': ['the rock is destined to be the 21st century\'s new " conan " and that he\'s going to make a splash even greater than arnold schwarzenegger , jean-claud van damme or steven segal .',
        'the gorgeously elaborate continuation of " the lord of the rings " trilogy is so huge that a column of words cannot adequately describe co-writer/director peter jackson\'s expanded vision of j . r . r . tolkien\'s middle-earth .',
        'effective but too-tepid biopic',
        'if you sometimes like to go to the movies to have fun , wasabi is a good place to start .'],
'label': [1, 1, 1, 1]}
```

O método `batch()` aceita os seguintes parâmetros:

- `batch_size` (`int`): O número de amostras em cada lote.
- `drop_last_batch` (`bool`, padrão `False`): Se deve descartar o último lote incompleto caso o tamanho do conjunto de dados não seja divisível pelo tamanho do lote.
- `num_proc` (`int`, opcional, padrão `None`): O número de processos a serem usados para multiprocessamento. Se for None, nenhum multiprocessamento é usado. Isso pode acelerar significativamente o loteamento para grandes conjuntos de dados.

Observe que `Dataset.batch()` retorna um novo [Dataset](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset) em que cada item é um lote de várias amostras do dataset original. Se você deseja processar dados em lotes, deve usar um [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) em lote diretamente, que aplica uma função a lotes, mas o dataset de saída não está em lote.

## Concatenar

Conjuntos de dados separados podem ser concatenados se compartilharem os mesmos tipos de colunas. Concatene conjuntos de dados com [concatenate_datasets()](/docs/datasets/main/pt/package_reference/main_classes#datasets.concatenate_datasets):

```py
>>> from datasets import concatenate_datasets, load_dataset

>>> stories = load_dataset("ajibawa-2023/General-Stories-Collection", split="train")
>>> stories = stories.select_columns(["text"])  # only keep the 'text' column
>>> wiki = load_dataset("wikimedia/wikipedia", "20231101.en", split="train")
>>> wiki = wiki.select_columns(["text"])  # only keep the 'text' column

>>> assert stories.features.type == wiki.features.type
>>> bert_dataset = concatenate_datasets([stories, wiki])
```

Você também pode concatenar dois conjuntos de dados horizontalmente definindo `axis=1`, desde que os conjuntos de dados tenham o mesmo número de linhas:

```py
>>> from datasets import Dataset
>>> stories_ids = Dataset.from_dict({"ids": list(range(len(stories)))})
>>> stories_with_ids = concatenate_datasets([stories, stories_ids], axis=1)
```

### Interlevar

Você também pode misturar vários conjuntos de dados, alternando exemplos de cada um para criar um novo conjunto de dados. Isso é conhecido como _interleaving_, habilitado pela função [interleave_datasets()](/docs/datasets/main/pt/package_reference/main_classes#datasets.interleave_datasets). Tanto [interleave_datasets()](/docs/datasets/main/pt/package_reference/main_classes#datasets.interleave_datasets) quanto [concatenate_datasets()](/docs/datasets/main/pt/package_reference/main_classes#datasets.concatenate_datasets) funcionam com objetos regulares de [Dataset](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset) e [IterableDataset](/docs/datasets/main/pt/package_reference/main_classes#datasets.IterableDataset). Consulte o guia de [Stream](./stream#interleave) para um exemplo de como intercalar objetos [IterableDataset](/docs/datasets/main/pt/package_reference/main_classes#datasets.IterableDataset).

Você pode definir probabilidades de amostragem para cada um dos conjuntos de dados originais para especificar como intercalar os conjuntos de dados. Nesse caso, o novo conjunto de dados é construído obtendo exemplos um a um de um conjunto de dados aleatório até que um dos conjuntos de dados fique sem amostras.

```py
>>> from datasets import Dataset, interleave_datasets
>>> seed = 42
>>> probabilities = [0.3, 0.5, 0.2]
>>> d1 = Dataset.from_dict({"a": [0, 1, 2]})
>>> d2 = Dataset.from_dict({"a": [10, 11, 12, 13]})
>>> d3 = Dataset.from_dict({"a": [20, 21, 22]})
>>> dataset = interleave_datasets([d1, d2, d3], probabilities=probabilities, seed=seed)
>>> dataset["a"]
[10, 11, 20, 12, 0, 21, 13]
```

Você também pode especificar o `stopping_strategy`. A estratégia padrão, `first_exhausted`, é uma estratégia de subsampling, ou seja, a construção do dataset é interrompida assim que um dos datasets fica sem amostras. Você pode especificar `stopping_strategy=all_exhausted` para executar uma estratégia de oversampling. Nesse caso, a construção do dataset é interrompida assim que todas as amostras de todos os datasets tiverem sido adicionadas pelo menos uma vez. Na prática, isso significa que, se um dataset for esgotado, ele voltará ao início desse dataset até que o critério de parada seja atingido. Observe que, se nenhuma probabilidade de amostragem for especificada, o novo dataset terá `max_length_datasets*nb_dataset samples`. Há também `stopping_strategy=all_exhausted_without_replacement` para garantir que cada amostra seja vista exatamente uma vez.

```py
>>> d1 = Dataset.from_dict({"a": [0, 1, 2]})
>>> d2 = Dataset.from_dict({"a": [10, 11, 12, 13]})
>>> d3 = Dataset.from_dict({"a": [20, 21, 22]})
>>> dataset = interleave_datasets([d1, d2, d3], stopping_strategy="all_exhausted")
>>> dataset["a"]
[0, 10, 20, 1, 11, 21, 2, 12, 22, 0, 13, 20]
```

## Formato

A função [with_format()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.with_format) altera o formato de uma coluna para que seja compatível com alguns formatos de dados comuns. Especifique a saída desejada no parâmetro `type`. Você também pode escolher quais colunas deseja formatar usando `columns=`. A formatação é aplicada em tempo real.

Por exemplo, crie tensores do PyTorch definindo `type="torch"`:

```py
>>> dataset = dataset.with_format(type="torch")
```

A função [set_format()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.set_format) também altera o formato de uma coluna, exceto que ela é executada in-place:

```py
>>> dataset.set_format(type="torch")
```

Se você precisar redefinir o dataset para seu formato original, defina o formato como `None` (ou use [reset_format()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.reset_format)):

```py
>>> dataset.format
{'type': 'torch', 'format_kwargs': {}, 'columns': [...], 'output_all_columns': False}
>>> dataset = dataset.with_format(None)
>>> dataset.format
{'type': None, 'format_kwargs': {}, 'columns': [...], 'output_all_columns': False}
```

### Formatos de tensores

Vários formatos de tensores ou arrays são suportados. Em geral, recomenda-se usar esses formatos em vez de converter manualmente as saídas de um dataset para tensores ou arrays, a fim de evitar cópias desnecessárias de dados e acelerar o carregamento dos dados.

Aqui está a lista de formatos de tensores ou arrays suportados:

- NumPy: o nome do formato é "numpy", para mais informações, consulte [Usando Datasets com NumPy](use_with_numpy)
- PyTorch: o nome do formato é "torch", para mais informações, consulte [Usando Datasets com PyTorch](use_with_pytorch)
- TensorFlow: o nome do formato é "tensorflow", para mais informações, consulte [Usando Datasets com TensorFlow](use_with_tensorflow)
- JAX: o nome do formato é "jax", para mais informações, consulte [Usando Datasets com JAX](use_with_jax)

> [!TIP]
> Confira o guia [Usando Datasets com TensorFlow](use_with_tensorflow#using-totfdataset) para mais detalhes sobre como criar um dataset do TensorFlow de forma eficiente.

Quando um conjunto de dados está formatado em formato de tensor ou array, todos os dados são formatados como tensors ou arrays (exceto tipos não suportados, como strings, por exemplo, para o PyTorch):

```python
>>> ds = Dataset.from_dict({"text": ["foo", "bar"], "tokens": [[0, 1, 2], [3, 4, 5]]})
>>> ds = ds.with_format("torch")
>>> ds[0]
{'text': 'foo', 'tokens': tensor([0, 1, 2])}
>>> ds[:2]
{'text': ['foo', 'bar'],
 'tokens': tensor([[0, 1, 2],
         [3, 4, 5]])}
```

### Formatos tabulares

Você pode usar o formato de dataframes ou tabelas para otimizar o carregamento e o processamento de dados, pois eles geralmente oferecem operações de cópia zero e transformações escritas em linguagens de baixo nível.

Aqui está a lista de formatos de dataframes ou tabelas suportados:

- Pandas: o nome do formato é "pandas", para mais informações, consulte [Usando Datasets com Pandas](use_with_pandas)
- Polars: o nome do formato é "polars", para mais informações, consulte [Usando Datasets com Polars](use_with_polars)
- PyArrow: o nome do formato é "arrow", para mais informações, consulte [Usando Datasets com PyArrow](use_with_tensorflow)

Quando um conjunto de dados está formatado em formato de dataframe ou tabela, cada linha do conjunto de dados ou lotes de linhas são formatados como um dataframe ou tabela, e as colunas do conjunto de dados são formatadas como uma série ou array:

```python
>>> ds = Dataset.from_dict({"text": ["foo", "bar"], "label": [0, 1]})
>>> ds = ds.with_format("pandas")
>>> ds[:2]
  text  label
0  foo      0
1  bar      1
```

Esses formatos permitem iterar sobre os dados mais rapidamente, evitando cópias de dados, e também habilitam um processamento de dados mais rápido em [map()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.map) ou [filter()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.filter):

```python
>>> ds = ds.map(lambda df: df.assign(upper_text=df.text.str.upper()), batched=True)
>>> ds[:2]
  text  label upper_text
0  foo      0        FOO
1  bar      1        BAR
```

### Transformação de formato personalizado

A função [with_transform()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.with_transform) aplica uma transformação de formatação personalizada em tempo real. Esta função substitui qualquer formato especificado anteriormente. Por exemplo, você pode usar esta função para tokenizar e aplicar padding aos tokens em tempo real. A tokenização é aplicada apenas quando os exemplos são acessados:

```py
>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
>>> def encode(batch):
...     return tokenizer(batch["sentence1"], batch["sentence2"], padding="longest", truncation=True, max_length=512, return_tensors="pt")
>>> dataset = dataset.with_transform(encode)
>>> dataset.format
{'type': 'custom', 'format_kwargs': {'transform': <function __main__.encode(batch)>}, 'columns': ['idx', 'label', 'sentence1', 'sentence2'], 'output_all_columns': False}
```

Há também [set_transform()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.set_transform), que faz o mesmo, mas executa in-place.

Você também pode usar a função [with_transform()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.with_transform) para decodificação personalizada em [Features](/docs/datasets/main/pt/package_reference/main_classes#datasets.Features).

O exemplo abaixo usa o pacote [`pydub`](http://pydub.com/) como alternativa à decodificação do `torchcodec`:

```py
>>> import numpy as np
>>> from pydub import AudioSegment

>>> audio_dataset_amr = Dataset.from_dict({"audio": ["audio_samples/audio.amr"]})

>>> def decode_audio_with_pydub(batch, sampling_rate=16_000):
...     def pydub_decode_file(audio_path):
...         sound = AudioSegment.from_file(audio_path)
...         if sound.frame_rate != sampling_rate:
...             sound = sound.set_frame_rate(sampling_rate)
...         channel_sounds = sound.split_to_mono()
...         samples = [s.get_array_of_samples() for s in channel_sounds]
...         fp_arr = np.array(samples).T.astype(np.float32)
...         fp_arr /= np.iinfo(samples[0].typecode).max
...         return fp_arr
...
...     batch["audio"] = [pydub_decode_file(audio_path) for audio_path in batch["audio"]]
...     return batch

>>> audio_dataset_amr.set_transform(decode_audio_with_pydub)
```

## Salvar

Quando seu conjunto de dados estiver pronto, você pode salvá-lo como um Dataset do Hugging Face no formato Parquet e reutilizá-lo mais tarde com [load_dataset()](/docs/datasets/main/pt/package_reference/loading_methods#datasets.load_dataset).

Salve seu dataset fornecendo o nome do repositório do dataset no Hugging Face para o qual você deseja salvá-lo em [push_to_hub()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.push_to_hub):

```python
encoded_dataset.push_to_hub("username/my_dataset")
```

Você pode usar múltiplos processos para enviá-lo em paralelo. Isso é especialmente útil se você quiser acelerar o processo:

```python
dataset.push_to_hub("username/my_dataset", num_proc=8)
```

Use a função [load_dataset()](/docs/datasets/main/pt/package_reference/loading_methods#datasets.load_dataset) para recarregar o conjunto de dados (em modo de streaming ou não):

```python
from datasets import load_dataset
reloaded_dataset = load_dataset("username/my_dataset", streaming=True)
```

Como alternativa, você pode salvá-lo localmente em formato Arrow no disco. Em comparação com Parquet, o Arrow não é compactado, o que o torna muito mais rápido para recarregar, o que é ótimo para uso local em disco e cache efêmero. Mas, como é maior e possui menos metadados, é mais lento para upload/download/consulta do que Parquet e menos adequado para armazenamento de longo prazo.

Use as funções [save_to_disk()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.save_to_disk) e [load_from_disk()](/docs/datasets/main/pt/package_reference/loading_methods#datasets.load_from_disk) para recarregar o dataset do seu disco:

```py
>>> encoded_dataset.save_to_disk("path/of/my/dataset/directory")
>>> # later
>>> from datasets import load_from_disk
>>> reloaded_dataset = load_from_disk("path/of/my/dataset/directory")
```

## Exportar

🤗 O Datasets também suporta exportação, para que você possa trabalhar com seu conjunto de dados em outros aplicativos. A tabela a seguir mostra os formatos de arquivo atualmente suportados para exportação:

| Tipo de arquivo               | Método de exportação                                                       |
| ----------------------- | ------------------------------------------------------------------- |
| CSV                     | [Dataset.to_csv()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.to_csv)                                                  |
| JSON                    | [Dataset.to_json()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.to_json)                                                 |
| Parquet                 | [Dataset.to_parquet()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.to_parquet)                                              |
| SQL                     | [Dataset.to_sql()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.to_sql)                                                  |
| Objeto Python em memória | [Dataset.to_pandas()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.to_pandas), `Dataset.to_polars()` or [Dataset.to_dict()](/docs/datasets/main/pt/package_reference/main_classes#datasets.Dataset.to_dict) |

Por exemplo, exporte seu conjunto de dados para um arquivo CSV da seguinte forma:

```py
>>> encoded_dataset.to_csv("path/of/my/dataset.csv")
```

Use um caminho `hf://` para exportar para um [repositório de Dataset](https://huggingface.co/docs/hub/datasets-overview) ou um [Storage Bucket](https://huggingface.co/docs/hub/storage-buckets) no Hugging Face:

```py
>>> encoded_dataset.to_csv("hf://datasets/username/dataset_name/path/of/my/dataset.csv")
>>> encoded_dataset.to_csv("hf://buckets/username/raw_data_bucket/path/of/my/dataset.csv")
```

