# 与 PyArrow 配合使用

本文档简要介绍了如何使用 `datasets` 与 PyArrow 配合工作，重点说明如何使用 Arrow 计算函数处理数据集，以及如何在数据集与 PyArrow 之间进行转换。

这一点尤其有用，因为 `datasets` 底层使用 PyArrow，从而支持快速的零拷贝操作。

## 数据集格式

默认情况下，数据集返回的是普通的 Python 对象：整数、浮点数、字符串、列表等。

若要获取 PyArrow 表或数组，可以使用 [Dataset.with_format()](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Dataset.with_format) 将数据集的格式设置为 `pyarrow`：

```py
>>> from datasets import Dataset
>>> data = {"col_0": ["a", "b", "c", "d"], "col_1": [0., 0., 1., 1.]}
>>> ds = Dataset.from_dict(data)
>>> ds = ds.with_format("arrow")
>>> ds[0]       # pa.Table
pyarrow.Table
col_0: string
col_1: double
----
col_0: [["a"]]
col_1: [[0]]
>>> ds[:2]      # pa.Table
pyarrow.Table
col_0: string
col_1: double
----
col_0: [["a","b"]]
col_1: [[0,0]]
>>> ds["data"]  # pa.array
<pyarrow.lib.ChunkedArray object at 0x1394312a0>
[
  [
    "a",
    "b",
    "c",
    "d"
  ]
]
```

对于例如使用 `load_dataset(..., streaming=True)` 获取的 `IterableDataset` 对象，此方法同样适用：

```py
>>> ds = ds.with_format("arrow")
>>> for table in ds.iter(batch_size=2):
...     print(table)
...     break
pyarrow.Table
col_0: string
col_1: double
----
col_0: [["a","b"]]
col_1: [[0,0]]
```

## 处理数据

PyArrow 函数通常比常规手写 Python 函数更快，因此是优化数据处理的理想选择。您可以在 [Dataset.map()](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Dataset.map) 或 [Dataset.filter()](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Dataset.filter) 中使用 Arrow 计算函数来处理数据集：

```python
>>> import pyarrow.compute as pc
>>> from datasets import Dataset
>>> data = {"col_0": ["a", "b", "c", "d"], "col_1": [0., 0., 1., 1.]}
>>> ds = Dataset.from_dict(data)
>>> ds = ds.with_format("arrow")
>>> ds = ds.map(lambda t: t.append_column("col_2", pc.add(t["col_1"], 1)), batched=True)
>>> ds[:2]
pyarrow.Table
col_0: string
col_1: double
col_2: double
----
col_0: [["a","b"]]
col_1: [[0,0]]
col_2: [[1,1]]
>>> ds = ds.filter(lambda t: pc.equal(t["col_0"], "b"), batched=True)
>>> ds[0]
pyarrow.Table
col_0: string
col_1: double
col_2: double
----
col_0: [["b"]]
col_1: [[0]]
col_2: [[1]]
```

我们使用 `batched=True`，因为在 PyArrow 中按批次处理数据比逐行处理更快。也可以在 `map()` 中使用 `batch_size=` 来设置每个 `table` 的大小。

这对 [IterableDataset.map()](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.IterableDataset.map) 和 [IterableDataset.filter()](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.IterableDataset.filter) 同样适用。

## 从 PyArrow 导入或导出

[Dataset](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Dataset) 是 PyArrow Table 的封装，您可以直接从 Table 实例化一个 Dataset：

```python
ds = Dataset(table)
```

您可以通过 [Dataset.data](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Dataset.data) 访问数据集的 PyArrow Table，根据 Arrow 数据的来源以及所执行的操作，它会返回 `MemoryMappedTable`、`InMemoryTable` 或 `ConcatenationTable`。

这些对象封装了位于 `Dataset.data.table` 处的底层 PyArrow 表。该表包含数据集的所有数据，但可能还存在一个位于 `Dataset._indices` 的索引映射，它将数据集的行索引映射到 PyArrow 表的行索引。如果数据集已通过 [Dataset.shuffle()](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Dataset.shuffle) 进行洗牌，或者仅使用了部分行（例如在 [Dataset.select()](/docs/datasets/v5.2.0/zh/package_reference/main_classes#datasets.Dataset.select) 之后），就可能出现这种情况。

在一般情况下，您可以使用 `table = ds.with_format("arrow")[:]` 将数据集导出为 PyArrow Table。

