# Proceso

🤗 Datasets ofrece muchas herramientas para modificar la estructura y el contenido de un conjunto de datos. Estas herramientas son importantes para ordenar un conjunto de datos, crear columnas adicionales, convertir entre características y formatos, y mucho más.

Esta guía te mostrará cómo:

- Reordena las filas y divide el conjunto de datos.
- Renombrar y eliminar columnas, y otras operaciones comunes de columnas.
- Aplicar funciones de procesamiento a cada ejemplo de un conjunto de datos.
- Concatenar conjuntos de datos.
- Aplicar una transformación de formato personalizada.
- Guardar y exportar conjuntos de datos procesados.

Para más detalles específicos sobre el procesamiento de otras modalidades de conjuntos de datos, consulte la guía para procesar conjuntos de datos de audio, la guía para procesar conjuntos de datos de imágenes o la guía para procesar conjuntos de datos de texto.

Los ejemplos de esta guía utilizan el conjunto de datos MRPC, pero no dude en cargar cualquier conjunto de datos de su elección y seguir el proceso.

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

> [!WARNING]
> Todos los métodos de procesamiento de esta guía devuelven un nuevo objeto [Dataset](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset). La modificación no se realiza in situ. ¡Tenga cuidado de no sobrescribir su conjunto de datos anterior!

## Ordenar, barajar, seleccionar, dividir y fragmentar

Existen varias funciones para reorganizar la estructura de un conjunto de datos. Estas funciones son útiles para seleccionar solo las filas que se desean, crear divisiones de entrenamiento y prueba, y dividir conjuntos de datos muy grandes en fragmentos más pequeños.

### Ordenar

Use [sort()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.sort) para ordenar los valores de la columna según sus valores numéricos. La columna proporcionada debe ser compatible con 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 debajo, esto crea una lista de índices ordenada según los valores de la columna. Este mapeo de índices se utiliza luego para acceder a las filas correctas en la tabla Arrow subyacente.

### Barajar

La función [shuffle()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.shuffle) reordena los valores de las columnas de forma aleatoria. Puede especificar el parámetro `generator` en esta función para utilizar un `numpy.random.Generator` diferente si desea tener más control sobre el algoritmo utilizado para barajar el conjunto de datos.

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

Shuffling toma la lista de índices `[0:len(my_dataset)]` y la baraja para crear un mapeo de índices. Sin embargo, en cuanto tu [Dataset](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset) tiene un mapeo de índices, la velocidad puede ser 10 veces más lenta. Esto se debe a que hay un paso adicional para obtener el índice de la fila a leer usando el mapeo de índices y, lo más importante, ya no estás leyendo fragmentos de datos contiguos. Para restaurar la velocidad, necesitarías reescribir todo el conjunto de datos en tu disco de nuevo usando [Dataset.flatten_indices()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.flatten_indices), que elimina el mapeo de índices. Alternativamente, puedes cambiar a un [IterableDataset](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.IterableDataset) y aprovechar su barajado aproximado rápido [IterableDataset.shuffle()](/docs/datasets/v5.2.0/es/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)
```

### Seleccionar y filtrar

Hay dos opciones para filtrar filas en un conjunto de datos: [select()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.select) y [filter()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.filter).

- [select()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.select) devuelve filas según una lista de índices:

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

- [filter()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.filter) devuelve las filas que cumplen una condición 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/v5.2.0/es/package_reference/main_classes#datasets.Dataset.filter) también puede filtrar por índices si estableces `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 la lista de índices a conservar sea contigua, esos métodos también crean un mapeo de índices por debajo.

### Dividir

La función [train_test_split()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.train_test_split) crea divisiones de entrenamiento y prueba si tu conjunto de datos no las tiene ya. Esto te permite ajustar las proporciones relativas o un número absoluto de muestras en cada división. En el ejemplo siguiente, usa el parámetro `test_size` para crear una división de prueba que sea el 10% del conjunto de datos 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
```

Los conjuntos de datos se barajan de forma predeterminada, pero puedes establecer `shuffle=False` para evitar el barajado.

### Fragmento

🤗 Datasets admite el particionado (sharding) para dividir un conjunto de datos muy grande en un número predefinido de fragmentos. Especifique el parámetro `num_shards` en [shard()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.shard) para determinar el número de fragmentos en los que se dividirá el conjunto de datos. También deberá proporcionar el fragmento que desea devolver mediante el parámetro `index`.

Por ejemplo, el conjunto de datos [stanfordnlp/imdb](https://huggingface.co/datasets/stanfordnlp/imdb) tiene 25000 ejemplos:

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

Tras dividir el conjunto de datos en cuatro fragmentos, el primer fragmento solo tendrá 6250 ejemplos:

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

## Renombrar, eliminar, convertir y aplanar

Las siguientes funciones permiten modificar las columnas de un conjunto de datos. Estas funciones son útiles para renombrar o eliminar columnas, cambiar columnas a un nuevo conjunto de características y aplanar estructuras de columnas anidadas.

### Renombrar

Use [rename_column()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.rename_column) cuando necesite renombrar una columna en su conjunto de datos. Las características asociadas con la columna original se mueven de hecho bajo el nuevo nombre de columna, en lugar de simplemente reemplazar la columna original en su lugar.

Proporcione a [rename_column()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.rename_column) el nombre de la columna original y el nuevo nombre de la columna:

```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
})
```

### Eliminar

Cuando necesite eliminar una o más columnas, proporcione el nombre de la columna a eliminar a la función [remove_columns()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.remove_columns). Para eliminar más de una columna, proporcione una lista de nombres de columnas:

```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 el contrario, [select_columns()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.select_columns) selecciona una o más columnas para conservar y elimina el resto. Esta función acepta un nombre de columna o una lista de nombres de columnas:

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

La función [cast()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.cast) transforma el tipo de característica de una o más columnas. Esta función acepta sus nuevas [Features](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Features) como argumento. El ejemplo de abajo demuestra cómo cambiar las características [ClassLabel](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.ClassLabel) y [Value](/docs/datasets/v5.2.0/es/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]
> El casting solo funciona si el tipo de característica original y el nuevo tipo de característica son compatibles. Por ejemplo, puedes hacer un casting de una columna con el tipo de característica `Value("int32")` a `Value("bool")` si la columna original solo contiene unos y ceros.

Use la función [cast_column()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.cast_column) para cambiar el tipo de característica de una sola columna. Pasa el nombre de la columna y su nuevo tipo de característica 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)}
```

### Aplanar

A veces, una columna puede ser una estructura anidada de varios tipos. Echa un vistazo a la estructura anidada a continuación del conjunto de datos 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'))}}
```

El campo `answers` contiene dos subcampos: `text` y `answer_start`. Utilice la función [flatten()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.flatten) para extraer los subcampos en columnas separadas:

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

Fíjate en cómo los subcampos ahora son columnas independientes: `answers.text` y `answers.answer_start`.

## Map

Algunas de las aplicaciones más potentes de 🤗 Datasets provienen del uso de la función [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map). El propósito principal de [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) es acelerar las funciones de procesamiento. Permite aplicar una función de procesamiento a cada ejemplo de un conjunto de datos, de forma independiente o en lotes. Esta función incluso puede crear nuevas filas y columnas.

En el siguiente ejemplo, antepóngase `'My sentence: '` a cada valor de `sentence1` en el conjunto de datos.

Comience creando una función que añade `'My sentence: '` al principio de cada oración. La función debe aceptar y devolver un `dict`:

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

Ahora usa [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) para aplicar la función `add_prefix` a todo el conjunto de datos:

```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 .',
]
```

Veamos otro ejemplo, pero esta vez eliminarás una columna con [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map). Al eliminar una columna, esta solo se elimina después de que el ejemplo se haya proporcionado a la función mapeada. Esto permite que la función mapeada utilice el contenido de las columnas antes de que se eliminen.

Especifica la columna a eliminar con el parámetro `remove_columns` en [map()](/docs/datasets/v5.2.0/es/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]
> 🤗 Datasets también tiene una función [remove_columns()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.remove_columns) que es más rápida porque no copia los datos de las columnas restantes.

También puede usar [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) con índices si establece `with_indices=True`. El ejemplo siguiente añade el índice al principio de cada oración:

```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 .'
]
```

### Multiprocesamiento

El procesamiento multiproceso acelera significativamente el procesamiento al paralelizar los procesos en la CPU. Establezca el parámetro `num_proc` en [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) para definir el número de procesos a utilizar:

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

El método [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) también funciona con el rango del proceso si se establece `with_rank=True`. Esto es análogo al parámetro `with_indices`. El parámetro `with_rank` en la función mapeada va después del parámetro `index` si este último ya está 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
...     )
```

El caso de uso principal de rank es paralelizar la computación en varias GPU. Esto requiere establecer `multiprocess.set_start_method("spawn")`. Si no lo haces, recibirás el siguiente error de CUDA:

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

### Procesamiento por lotes

La función [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) permite trabajar con lotes de ejemplos. Para operar con lotes, establezca `batched=True`. El tamaño de lote predeterminado es 1000, pero puede ajustarlo con el parámetro `batch_size`. El procesamiento por lotes habilita aplicaciones interesantes, como dividir oraciones largas en fragmentos más cortos y el aumento de datos.

#### Dividir ejemplos largos

Cuando los ejemplos son demasiado largos, es posible que desee dividirlos en varios fragmentos más pequeños. Comience creando una función que:

1. Divide el campo `sentence1` en fragmentos de 50 caracteres.

2. Apila todos los fragmentos para crear el nuevo conjunto de datos.

```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}
```

Aplica la función con [map()](/docs/datasets/v5.2.0/es/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']}
```

Fíjate en cómo las frases se dividen ahora en fragmentos más cortos y hay más filas en el conjunto de datos.

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

#### Aumento de datos

La función [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) también se puede utilizar para el aumento de datos. El siguiente ejemplo genera palabras adicionales para un token enmascarado en una oración.

Carga y usa el modelo [RoBERTa](https://huggingface.co/roberta-base) en [FillMaskPipeline](https://huggingface.co/transformers/main_classes/pipelines#transformers.FillMaskPipeline) de 🤗 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)
```

Cree una función para seleccionar aleatoriamente una palabra para enmascarar en la oración. La función también debe devolver la oración original y los dos reemplazos principales generados por 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/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) para aplicar la función a todo el conjunto de datos:

```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 oración original, RoBERTA aumentó una palabra aleatoria con tres alternativas. La palabra original `distorting` se complementa con `withholding`, `suppressing` y `destroying`.

### Procesamiento asíncrono

Las funciones asíncronas son útiles para llamar a puntos finales de API en paralelo, por ejemplo, para descargar contenido como imágenes o llamar a un punto final de un modelo.

Puede definir una función asíncrona utilizando las palabras clave `async` y `await`; a continuación, se muestra una función de ejemplo para llamar a un modelo de chat de 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"]}
```

Las funciones asíncronas se ejecutan en paralelo, lo que acelera mucho el proceso. El mismo código tarda mucho más tiempo si se ejecuta de forma secuencial, ya que no hace nada mientras espera la respuesta del modelo. En general, se recomienda usar `async` / `await` cuando una función debe esperar una respuesta de una API, por ejemplo, o si descarga datos y puede tardar algún tiempo.

Tenga en cuenta la presencia de un `Semaphore`: establece el número máximo de consultas que pueden ejecutarse en paralelo. Se recomienda usar un `Semaphore` al llamar a APIs para evitar errores de límite de tasa.

Usémoslo para llamar al modelo [microsoft/Phi-3-mini-4k-instruct](https://huggingface.co/microsoft/Phi-3-mini-4k-instruct) y pedirle que devuelva el tema principal de cada problema de matemáticas del conjunto de datos [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.'}
````

Aquí, [Dataset.map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) ejecuta muchas funciones `get_topic` de forma asíncrona para no tener que esperar a cada respuesta del modelo, lo cual tomaría mucho tiempo si se hiciera de forma secuencial.

Por defecto, [Dataset.map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) ejecuta hasta mil funciones de mapeo en paralelo, por lo que no olvide establecer el número máximo de llamadas a la API que pueden ejecutarse en paralelo con un `Semaphore`; de lo contrario, el modelo podría devolver errores de límite de tasa o sobrecarga. Para casos de uso avanzados, puede cambiar el número máximo de consultas en paralelo en `datasets.config`.

### Procesar múltiples divisiones

Muchos conjuntos de datos tienen divisiones que pueden procesarse simultáneamente con [DatasetDict.map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.DatasetDict.map). Por ejemplo, tokenice el campo `sentence1` en las divisiones de entrenamiento y prueba mediante:

```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 distribuido

Cuando se utiliza [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) en un entorno distribuido, también se debe usar [torch.distributed.barrier](https://pytorch.org/docs/stable/distributed?highlight=barrier#torch.distributed.barrier). Esto garantiza que el proceso principal realice el mapeo, mientras que los demás procesos cargan los resultados, evitando así el trabajo duplicado.

El siguiente ejemplo muestra cómo puedes usar `torch.distributed.barrier` para sincronizar los procesos:

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

El método `batch()` permite agrupar muestras del conjunto de datos en lotes. Esto resulta especialmente útil cuando se desea crear lotes de datos para el entrenamiento o la evaluación, en particular al trabajar con modelos de aprendizaje profundo.

A continuación se muestra un ejemplo de cómo usar el 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]}
```

El método `batch()` acepta los siguientes parámetros:

- `batch_size` (`int`): El número de muestras en cada lote.
- `drop_last_batch` (`bool`, por defecto `False`): Si se debe descartar el último lote incompleto cuando el tamaño del conjunto de datos no es divisible por el tamaño del lote.
- `num_proc` (`int`, opcional, valor predeterminado `None`): El número de procesos a utilizar para la multiprocesación. Si es None, no se utiliza multiprocesación. Esto puede acelerar significativamente el procesamiento por lotes para conjuntos de datos grandes.

Tenga en cuenta que `Dataset.batch()` devuelve un nuevo [Dataset](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset) en el que cada elemento es un lote de varias muestras del conjunto de datos original. Si desea procesar datos por lotes, debe usar directamente un [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) por lotes, que aplica una función a los lotes, pero el conjunto de datos de salida no está loteado.

## Concatenar

Los conjuntos de datos separados pueden concatenarse si comparten los mismos tipos de columnas. Concatene los conjuntos de datos con [concatenate_datasets()](/docs/datasets/v5.2.0/es/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])
```

También puede concatenar dos conjuntos de datos horizontalmente estableciendo `axis=1`, siempre que los conjuntos de datos tengan el mismo número de filas:

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

### Interleaved

También puedes combinar varios conjuntos de datos tomando ejemplos alternos de cada uno para crear un nuevo conjunto de datos. Esto se conoce como _interleaving_, que se habilita mediante la función [interleave_datasets()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.interleave_datasets). Tanto [interleave_datasets()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.interleave_datasets) como [concatenate_datasets()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.concatenate_datasets) funcionan con objetos [Dataset](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset) y [IterableDataset](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.IterableDataset) regulares. Consulta la guía de [Stream](./stream#interleave) para ver un ejemplo de cómo intercalar objetos [IterableDataset](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.IterableDataset).

Puede definir probabilidades de muestreo para cada uno de los conjuntos de datos originales para especificar cómo intercalar los conjuntos de datos. En este caso, el nuevo conjunto de datos se construye obteniendo ejemplos uno a uno de un conjunto de datos aleatorio hasta que uno de los conjuntos de datos se quede sin muestras.

```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]
```

También puede especificar `stopping_strategy`. La estrategia predeterminada, `first_exhausted`, es una estrategia de muestreo parcial, es decir, la construcción del conjunto de datos se detiene en cuanto uno de los conjuntos de datos se queda sin muestras. Puede especificar `stopping_strategy=all_exhausted` para ejecutar una estrategia de muestreo excesivo. En este caso, la construcción del conjunto de datos se detiene en cuanto todas las muestras de todos los conjuntos de datos se hayan añadido al menos una vez. En la práctica, esto significa que si un conjunto de datos se agota, volverá al principio de ese conjunto de datos hasta que se alcance el criterio de parada. Tenga en cuenta que si no se especifican probabilidades de muestreo, el nuevo conjunto de datos tendrá `max_length_datasets*nb_dataset samples`. También existe `stopping_strategy=all_exhausted_without_replacement` para garantizar que cada muestra se vea exactamente una 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

La función [with_format()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.with_format) cambia el formato de una columna para que sea compatible con algunos formatos de datos comunes. Especifique el formato de salida deseado en el parámetro `type`. También puede elegir qué columnas desea formatear usando `columns=`. El formateo se aplica al vuelo.

Por ejemplo, crea tensores de PyTorch estableciendo `type="torch"`:

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

La función [set_format()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.set_format) también cambia el formato de una columna, pero se ejecuta in situ:

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

Si necesitas restablecer el conjunto de datos a su formato original, establece el formato en `None` (o usa [reset_format()](/docs/datasets/v5.2.0/es/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

Se admiten varios formatos de tensores o matrices. En general, se recomienda utilizar estos formatos en lugar de convertir manualmente las salidas de un conjunto de datos a tensores o matrices, para evitar copias de datos innecesarias y acelerar la carga de datos.

Esta es la lista de formatos de tensores o matrices admitidos:

- NumPy: el nombre del formato es "numpy", para más información consulte [Uso de Datasets con NumPy](use_with_numpy)
- PyTorch: el nombre del formato es "torch", para más información consulte [Uso de Datasets con PyTorch](use_with_pytorch)
- TensorFlow: el nombre del formato es "tensorflow", para más información consulte [Uso de Datasets con TensorFlow](use_with_tensorflow)
- JAX: el nombre del formato es "jax", para más información consulte [Uso de Datasets con JAX](use_with_jax)

> [!TIP]
> Consulte la guía [Uso de Datasets con TensorFlow](use_with_tensorflow#using-totfdataset) para obtener más detalles sobre cómo crear un dataset de TensorFlow de manera eficiente.

Cuando un conjunto de datos está formateado en formato de tensor o matriz, todos los datos se formatean como tensores o matrices (excepto los tipos no compatibles, como las cadenas de texto, por ejemplo, para 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

Puede usar un formato de dataframes o tablas para optimizar la carga y el procesamiento de datos, ya que generalmente ofrecen operaciones sin copia y transformaciones escritas en lenguajes de bajo nivel.

Esta es la lista de formatos de dataframes o tablas admitidos:

- Pandas: el nombre del formato es "pandas", para más información consulte [Uso de conjuntos de datos con Pandas](use_with_pandas)
- Polars: el nombre del formato es "polars", para más información consulte [Uso de Datasets con Polars](use_with_polars)
- PyArrow: el nombre del formato es "arrow", para más información consulte [Uso de Datasets con PyArrow](use_with_tensorflow)

Cuando un conjunto de datos está formateado en formato de dataframe o tabla, cada fila del conjunto de datos o lotes de filas se formatean como un dataframe o tabla, y las columnas del conjunto de datos se formatean como una serie o un 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
```

Esos formatos permiten iterar sobre los datos más rápido al evitar copias de datos, y también habilitan un procesamiento de datos más rápido en [map()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.map) o [filter()](/docs/datasets/v5.2.0/es/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
```

### Transformación de formato personalizado

La función [with_transform()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.with_transform) aplica una transformación de formato personalizada al vuelo. Esta función reemplaza cualquier formato especificado previamente. Por ejemplo, puede usar esta función para tokenizar y rellenar tokens al vuelo. La tokenización solo se aplica cuando se accede a los ejemplos:

```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}
```

También existe [set_transform()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.set_transform), que realiza la misma función pero de forma in situ.

También puede usar la función [with_transform()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.with_transform) para decodificación personalizada en [Features](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Features).

El ejemplo siguiente utiliza el paquete [`pydub`](http://pydub.com/) como alternativa a la decodificación de `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)
```

## Guardar

Una vez que tu conjunto de datos esté listo, puedes guardarlo como un Dataset de Hugging Face en formato Parquet y reutilizarlo más adelante con [load_dataset()](/docs/datasets/v5.2.0/es/package_reference/loading_methods#datasets.load_dataset).

Guarde su conjunto de datos proporcionando el nombre del repositorio de conjuntos de datos en Hugging Face al que desea guardarlo en [push_to_hub()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.push_to_hub):

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

Puedes usar varios procesos para subirlo en paralelo. Esto es especialmente útil si quieres acelerar el proceso:

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

Use la función [load_dataset()](/docs/datasets/v5.2.0/es/package_reference/loading_methods#datasets.load_dataset) para recargar el conjunto de datos (en modo streaming o no):

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

Como alternativa, puede guardarlo localmente en formato Arrow en el disco. En comparación con Parquet, Arrow no está comprimido, lo que lo hace mucho más rápido de recargar, ideal para uso local en disco y caché efímera. Sin embargo, al ser más grande y tener menos metadatos, es más lento para subir, descargar o consultar que Parquet y es menos adecuado para almacenamiento a largo plazo.

Use las funciones [save_to_disk()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.save_to_disk) y [load_from_disk()](/docs/datasets/v5.2.0/es/package_reference/loading_methods#datasets.load_from_disk) para recargar el conjunto de datos desde su 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

🤗 Datasets también permite la exportación, de modo que puedas trabajar con tu conjunto de datos en otras aplicaciones. La siguiente tabla muestra los formatos de archivo actualmente admitidos para la exportación:

| Tipo de archivo               | Método de exportación                                                       |
| ----------------------- | ------------------------------------------------------------------- |
| CSV                     | [Dataset.to_csv()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.to_csv)                                                  |
| JSON                    | [Dataset.to_json()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.to_json)                                                 |
| Parquet                 | [Dataset.to_parquet()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.to_parquet)                                              |
| SQL                     | [Dataset.to_sql()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.to_sql)                                                  |
| Objeto de Python en memoria | [Dataset.to_pandas()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.to_pandas), `Dataset.to_polars()` or [Dataset.to_dict()](/docs/datasets/v5.2.0/es/package_reference/main_classes#datasets.Dataset.to_dict) |

Por ejemplo, exporte su conjunto de datos a un archivo CSV de la siguiente manera:

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

Use una ruta `hf://` para exportar a un [repositorio de Dataset](https://huggingface.co/docs/hub/datasets-overview) o a un [Storage Bucket](https://huggingface.co/docs/hub/storage-buckets) en 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")
```

