# Pandas

[Pandas](https://github.com/pandas-dev/pandas)は広く利用されているPythonのデータ分析ツールキットです。[fsspec](https://filesystem-spec.readthedocs.io)を使用してリモートデータの読み書きを行うため、Hugging Faceのパス（[`hf://`](/docs/huggingface_hub/guides/hf_file_system#integrations)）を使ってHub上のデータの読み書きを行うことができます。

## DataFrameの読み込み

ローカルファイルやHugging Face Datasetsなどのリモートストレージからデータをロードできます。PandasはCSV、JSON、Parquetなど多くの形式をサポートしています:

```python
>>> import pandas as pd
>>> df = pd.read_csv("path/to/data.csv")
```

Hugging Face からファイルを読み込むには、パスの先頭に `hf://` を付ける必要があります。例えば、[stanfordnlp/imdb](https://huggingface.co/datasets/stanfordnlp/imdb) データセットリポジトリへのパスは `hf://datasets/stanfordnlp/imdb` です。Hugging Face 上のこのデータセットには複数の Parquet ファイルが含まれています。Parquet ファイル形式は、データフレームの読み書きを効率的に行い、データ分析言語間でデータを共有することを容易にするために設計されています。`plain_text/train-00000-of-00001.parquet` ファイルを読み込む方法は以下の通りです。

```python
>>> import pandas as pd
>>> df = pd.read_parquet("hf://datasets/stanfordnlp/imdb/plain_text/train-00000-of-00001.parquet")
>>> df
                                                    text  label
0      I rented I AM CURIOUS-YELLOW from my video sto...      0
1      "I Am Curious: Yellow" is a risible and preten...      0
2      If only to avoid making this type of film in t...      0
3      This film was probably inspired by Godard's Ma...      0
4      Oh, brother...after hearing about this ridicul...      0
...                                                  ...    ...
24995  A hit at the time but now better categorised a...      1
24996  I love this movie like no other. Another time ...      1
24997  This film and it's sequel Barry Mckenzie holds...      1
24998  'The Adventures Of Barry McKenzie' started lif...      1
24999  The story centers around Barry McKenzie who mu...      1
```

Hugging Face のパスとその実装方法に関する詳細については、[HfFileSystem に関するクライアントライブラリのドキュメント](/docs/huggingface_hub/guides/hf_file_system)を参照してください。

> [!TIP]
> 同じ`hf://`パスは、[Storage Buckets](./storage-buckets)でも機能します:
> ```python
> >>> df = pd.read_parquet("hf://buckets/username/my-bucket/data.parquet")
> >>> df.to_parquet("hf://buckets/username/my-bucket/output.parquet")
> ```

## DataFrameを保存する

`to_csv/to_json/to_parquet` を使用して、pandas の DataFrame をローカルファイルや Hugging Face に直接保存できます。

Hugging Face に DataFrame を保存するには、まず [Hugging Face アカウントでログイン](/docs/huggingface_hub/quick-start#login) する必要があります。例えば、以下のように使用します:

```
hf auth login
```

その後、[データセットリポジトリを作成](/docs/huggingface_hub/quick-start#create-a-repository)できます。例えば、以下のように使用します:

```python
from huggingface_hub import HfApi

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

最後に、Pandas で[Hugging Face パス](/docs/huggingface_hub/guides/hf_file_system#integrations)を使用できます:

```python
import pandas as pd

df.to_parquet("hf://datasets/username/my_dataset/imdb.parquet")

# or write in separate files if the dataset has train/validation/test splits
df_train.to_parquet("hf://datasets/username/my_dataset/train.parquet")
df_valid.to_parquet("hf://datasets/username/my_dataset/validation.parquet")
df_test .to_parquet("hf://datasets/username/my_dataset/test.parquet")
```

Hugging Face上のParquetファイルは、ストレージ効率の向上、ダウンロードおよびアップロードの高速化、効率的なデータセットのストリーミングと編集を可能にするよう最適化されています。

* [Parquet Content Defined Chunking](https://huggingface.co/blog/parquet-cdc) は、Hugging Face のストレージバックエンドである [Xet](https://huggingface.co/docs/hub/en/xet/index) 向けに Parquet を最適化します。チャンクベースの重複排除によりアップロードとダウンロードを高速化し、効率的なファイル編集を可能にします。
* ページインデックスはストリーミング時のフィルタリングを高速化し、[Dataset Viewer](https://huggingface.co/docs/dataset-viewer) での効率的なランダムアクセスを可能にします。

Pandasで最適化されたParquetファイルを書き出すには、追加の引数が必要です:

```python
import pandas as pd

df.to_parquet(
    "hf://datasets/username/my_dataset/imdb.parquet",
    # Optimize for Xet
    use_content_defined_chunking=True,
    write_page_index=True,
)
```

* `use_content_defined_chunking=True` を設定して Parquet Content Defined Chunking を有効にし、[重複排除](https://huggingface.co/blog/parquet-cdc)および[編集](./datasets-editing)に対応します（`pyarrow>=21.0` が必要です）
* `write_page_index=True` を設定すると、[ストリーミングおよびランダムアクセス](./datasets-streaming)のために Parquet メタデータにページインデックスが含まれます。

> [!TIP]
> Content defined chunking（CDC）により、Parquet writer は重複するデータを同一にチャンク化・圧縮できるように、データページをチャンク化します。CDC を使用しない場合、ページは任意にチャンク化されるため、圧縮の影響により重複データの検出が不可能になります。CDC により、重複データは一度だけアップロードまたはダウンロードされるため、Hugging Face への Parquet のアップロードとダウンロードが高速化されます。

Xetの詳細については、[こちら](https://huggingface.co/join/xet)をご覧ください。

## Parquet での Xet の重複排除を活用

最適化された Parquet ファイルは、重複排除を可能にする Content Defined Chunking を用いて書き込まれます。これにより、Hugging Face に既に存在するデータチャンクを再アップロードする必要がなくなるため、アップロードが高速化され、I/O が大幅に節約されます。

例えば、このコードは`df`の内容をアップロードし、その後`edited_df`のアップロードは変更されたチャンクのみをアップロードするため、より高速になります。

```python
import pandas as pd

df.to_parquet(
    "hf://datasets/username/my_dataset/imdb.parquet",
    # Optimize for Xet
    use_content_defined_chunking=True,
    write_page_index=True,
)

edited_df = ...  # e.g. with added/modified/removed rows or columns

edited_df.to_parquet(
    "hf://datasets/username/my_dataset/imdb.parquet",
    # Optimize for Xet
    use_content_defined_chunking=True,
    write_page_index=True,
)
```

チャンクは約64kBであり、Parquetはカラムごとにデータを保存するため、Optimized Parquetファイルを編集する際に実際に起こることは以下の通りです。

* 新しい列を追加 -> 新しい列のチャンクのみがアップロードされます
* 行の追加/編集/削除 -> 各カラムごとに1つのチャンクがアップロードされます

さらに、メタデータを含むParquetフッターのチャンクもアップロードされます。

## 画像の使用

メタデータファイルに画像の名前またはパスを格納するフィールドを含み、次のように構成されたフォルダを読み込むことができます。

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

画像のパスを次のように反復処理できます。

```python
import pandas as pd

folder_path = "path/to/folder/"
df = pd.read_csv(folder_path + "metadata.csv")
for image_path in (folder_path + df["file_name"]):
    ...
```

データセットが[サポートされている構造](https://huggingface.co/docs/hub/en/datasets-image#additional-columns)（`file_name`フィールドを持つ`metadata.csv`または`.jsonl`ファイル）であるため、このデータセットをHugging Faceに保存すると、Dataset ViewerがHugging Face上でメタデータと画像の両方を表示します。

```python
from huggingface_hub import HfApi
api = HfApi()

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

### 画像メソッドとParquet

[pandas-image-methods](https://github.com/lhoestq/pandas-image-methods) を使用すると、画像カラムに対して`PIL.Image`のメソッドを有効にできます。また、画像とメタデータの両方を含む単一の Parquet ファイルとしてデータセットを保存することも可能になります。

```python
import pandas as pd
from pandas_image_methods import PILMethods

pd.api.extensions.register_series_accessor("pil")(PILMethods)

df["image"] = (folder_path + df["file_name"]).pil.open()
df.to_parquet("data.parquet")
```

`PIL.Image`のすべてのメソッドが利用可能であり、例えば

```python
df["image"] = df["image"].pil.rotate(90)
```

## Audiosを使用する

メタデータファイルを含むフォルダを読み込むことができます。このメタデータファイルには、オーディオの名前またはパスを格納するフィールドが含まれており、以下のように構成されています。

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

オーディオのパスを次のように反復処理できます。

```python
import pandas as pd

folder_path = "path/to/folder/"
df = pd.read_csv(folder_path + "metadata.csv")
for audio_path in (folder_path + df["file_name"]):
    ...
```

データセットが[サポートされている構造](https://huggingface.co/docs/hub/en/datasets-audio#additional-columns)（`file_name`フィールドを持つ`metadata.csv`または`.jsonl`ファイル）であるため、Hugging Face に保存すると、Hub Dataset Viewer でメタデータとオーディオの両方が表示されます。

```python
from huggingface_hub import HfApi
api = HfApi()

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

### オーディオメソッドとParquet

[pandas-audio-methods](https://github.com/lhoestq/pandas-audio-methods) を使用すると、オーディオカラムに対して`soundfile` のメソッドを有効にできます。また、オーディオとメタデータの両方を含む単一の Parquet ファイルとしてデータセットを保存することも可能になります。

```python
import pandas as pd
from pandas_audio_methods import SFMethods

pd.api.extensions.register_series_accessor("sf")(SFMethods)

df["audio"] = (folder_path + df["file_name"]).sf.open()
df.to_parquet("data.parquet")
```

これにより、`librosa`と組み合わせて使用しやすくなります。例えば、リサンプリングを行う場合:

```python
df["audio"] = [librosa.load(audio, sr=16_000) for audio in df["audio"]]
df["audio"] = df["audio"].sf.write()
```

## Transformersを使用する

`transformers`のパイプラインは、pandasのDataFrameに対して分類やテキスト・画像の生成などの処理を行うことができます。このセクションでは、進捗バーを表示するために`tqdm`を使用するいくつかの例を示します。

> [!TIP]
> Pipelinesは`tqdm`オブジェクトを入力として受け取りませんが、代わりに`x for x in tqdm(...)`という形式のPythonジェネレーターを使用できます。

### テキスト分類

```python
from transformers import pipeline
from tqdm import tqdm

pipe = pipeline("text-classification", model="clapAI/modernBERT-base-multilingual-sentiment")

# Compute labels
df["label"] = [y["label"] for y in pipe(x for x in tqdm(df["text"]))]
# Compute labels and scores
df[["label", "score"]] = [(y["label"], y["score"]) for y in pipe(x for x in tqdm(df["text"]))]
```

### テキスト生成

```python
from transformers import pipeline
from tqdm import tqdm

pipe = pipeline("text-generation", model="Qwen/Qwen2.5-1.5B-Instruct")

# Generate chat response
prompt = "What is the main topic of this sentence ? REPLY IN LESS THAN 3 WORDS. Sentence: '{}'"
df["output"] = [y["generated_text"][1]["content"] for y in pipe([{"role": "user", "content": prompt.format(x)}] for x in tqdm(df["text"]))]
```

