# Pandas

[Pandas](https://github.com/pandas-dev/pandas) là bộ công cụ phân tích dữ liệu Python được sử dụng rộng rãi. Vì nó sử dụng [fsspec](https://filesystem-spec.readthedocs.io) để đọc và ghi dữ liệu từ xa, bạn có thể sử dụng các đường dẫn Hugging Face ([`hf://`](/docs/huggingface_hub/guides/hf_file_system#integrations)) để đọc và ghi dữ liệu trên Hub.

## Tải một DataFrame

Bạn có thể tải dữ liệu từ các tệp cục bộ hoặc từ bộ lưu trữ từ xa như Hugging Face Datasets. Pandas hỗ trợ nhiều định dạng bao gồm CSV, JSON và Parquet:

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

Để tải một tệp từ Hugging Face, đường dẫn phải bắt đầu bằng `hf://`. Ví dụ, đường dẫn đến kho dữ liệu [stanfordnlp/imdb](https://huggingface.co/datasets/stanfordnlp/imdb) là `hf://datasets/stanfordnlp/imdb`. Dữ liệu trên Hugging Face chứa nhiều tệp Parquet. Định dạng tệp Parquet được thiết kế để đọc và ghi các data frame hiệu quả, đồng thời giúp việc chia sẻ dữ liệu giữa các ngôn ngữ phân tích dữ liệu trở nên dễ dàng. Dưới đây là cách tải tệp `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
```

Để biết thêm thông tin về các đường dẫn của Hugging Face và cách chúng được triển khai, vui lòng tham khảo [tài liệu của thư viện client về HfFileSystem](/docs/huggingface_hub/guides/hf_file_system).

> [!TIP]
> Các đường dẫn `hf://` tương tự cũng hoạt động với [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")
> ```

## Lưu một DataFrame

Bạn có thể lưu một DataFrame pandas bằng cách sử dụng `to_csv/to_json/to_parquet` vào một tệp cục bộ hoặc trực tiếp lên Hugging Face.

Để lưu DataFrame trên Hugging Face, trước tiên bạn cần [Đăng nhập bằng tài khoản Hugging Face](/docs/huggingface_hub/quick-start#login), ví dụ bằng cách sử dụng:

```
hf auth login
```

Sau đó, bạn có thể [Tạo kho dữ liệu](/docs/huggingface_hub/quick-start#create-a-repository), ví dụ bằng cách sử dụng:

```python
from huggingface_hub import HfApi

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

Cuối cùng, bạn có thể sử dụng [đường dẫn Hugging Face](/docs/huggingface_hub/guides/hf_file_system#integrations) trong Pandas:

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

Lưu ý rằng các tệp Parquet trên Hugging Face được tối ưu hóa để cải thiện hiệu quả lưu trữ, tăng tốc quá trình tải xuống và tải lên, cũng như cho phép phát trực tiếp và chỉnh sửa bộ dữ liệu một cách hiệu quả:

* [Phân chia chunk theo nội dung Parquet](https://huggingface.co/blog/parquet-cdc) tối ưu hóa Parquet cho [Xet](https://huggingface.co/docs/hub/en/xet/index), hệ thống lưu trữ phía sau của Hugging Face. Nó tăng tốc quá trình tải lên và tải xuống nhờ khử trùng lặp dựa trên chunk và cho phép chỉnh sửa tệp hiệu quả
* Chỉ mục trang (Page index) tăng tốc bộ lọc khi phát trực tiếp và cho phép truy cập ngẫu nhiên hiệu quả, ví dụ như trong [Dataset Viewer](https://huggingface.co/docs/dataset-viewer)

Pandas yêu cầu thêm đối số để ghi các tệp Parquet được tối ưu hóa:

```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` để bật Parquet Content Defined Chunking, phục vụ cho [loại bỏ trùng lặp](https://huggingface.co/blog/parquet-cdc) và [chỉnh sửa](./datasets-editing) (yêu cầu `pyarrow>=21.0`)
* `write_page_index=True` để bao gồm chỉ mục trang trong metadata Parquet, phục vụ cho [streaming và truy cập ngẫu nhiên](./datasets-streaming)

> [!TIP]
> Chunking dựa trên nội dung (CDC) cho phép trình ghi Parquet chia dữ liệu thành các trang theo cách khiến dữ liệu trùng lặp được chia và nén giống hệt nhau. Nếu không có CDC, các trang sẽ được chia một cách tùy ý, do đó không thể phát hiện dữ liệu trùng lặp do quá trình nén. Nhờ CDC, việc tải lên và tải xuống Parquet từ Hugging Face nhanh hơn, vì dữ liệu trùng lặp chỉ được tải lên hoặc tải xuống một lần.

Tìm thêm thông tin về Xet [tại đây](https://huggingface.co/join/xet).

## Tận dụng tính năng khử trùng lặp của Xet cho Parquet

Các tệp Parquet được tối ưu hóa được ghi với Content Defined Chunking, cho phép loại bỏ trùng lặp. Điều này tăng tốc quá trình tải lên vì các khối dữ liệu đã tồn tại trên Hugging Face không cần phải tải lên lại, và điều này tiết kiệm được rất nhiều I/O.

Ví dụ, đoạn mã này tải lên nội dung của `df` và sau đó với `edited_df` quá trình tải lên sẽ nhanh hơn vì nó chỉ tải lên các khối đã thay đổi:

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

Các chunk có kích thước ~64kB và Parquet lưu trữ dữ liệu theo từng cột, vì vậy trên thực tế, đây là những gì xảy ra khi chỉnh sửa một tệp Optimized Parquet:

* thêm một cột mới -> chỉ các khối của cột mới được tải lên
* thêm/sửa/xóa một hàng -> một chunk cho mỗi cột được tải lên

Ngoài ra, các khối của phần chân Parquet chứa dữ liệu mô tả cũng được tải lên.

## Sử dụng hình ảnh

Bạn có thể tải một thư mục chứa tệp metadata có trường cho tên hoặc đường dẫn đến các hình ảnh, được cấu trúc như sau:

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

Bạn có thể lặp qua các đường dẫn ảnh như sau:

```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"]):
    ...
```

Vì tập dữ liệu có [cấu trúc được hỗ trợ](https://huggingface.co/docs/hub/en/datasets-image#additional-columns) (tệp `metadata.csv` hoặc `.jsonl` có trường `file_name`), bạn có thể lưu tập dữ liệu này lên Hugging Face và Dataset Viewer sẽ hiển thị cả metadata và hình ảnh trên 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",
)
```

### Phương pháp hình ảnh và Parquet

Sử dụng [pandas-image-methods](https://github.com/lhoestq/pandas-image-methods), bạn có thể kích hoạt các phương thức của `PIL.Image` trên một cột ảnh. Nó cũng cho phép lưu bộ dữ liệu dưới dạng một tệp Parquet duy nhất chứa cả hình ảnh và metadata:

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

Tất cả các phương thức của `PIL.Image` đều khả dụng, ví dụ

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

## Sử dụng Audios

Bạn có thể tải một thư mục chứa tệp metadata có trường cho tên hoặc đường dẫn đến các tệp âm thanh, được cấu trúc như sau:

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

Bạn có thể lặp qua các đường dẫn âm thanh như sau:

```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"]):
    ...
```

Vì tập dữ liệu có [cấu trúc được hỗ trợ](https://huggingface.co/docs/hub/en/datasets-audio#additional-columns) (tệp `metadata.csv` hoặc `.jsonl` có trường `file_name`), bạn có thể lưu nó lên Hugging Face, và Hub Dataset Viewer sẽ hiển thị cả metadata lẫn audio.

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

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

### Phương pháp Audio và Parquet

Sử dụng [pandas-audio-methods](https://github.com/lhoestq/pandas-audio-methods), bạn có thể kích hoạt các phương thức `soundfile` trên một cột âm thanh. Nó cũng cho phép lưu bộ dữ liệu dưới dạng một tệp Parquet duy nhất chứa cả âm thanh và metadata:

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

Điều này giúp việc sử dụng với `librosa` trở nên dễ dàng, ví dụ như để lấy lại mẫu:

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

## Sử dụng Transformers

Bạn có thể sử dụng pipeline của `transformers` trên các DataFrame của pandas để phân loại, tạo văn bản, hình ảnh, v.v. Phần này trình bày một vài ví dụ với `tqdm` cho thanh tiến trình.

> [!TIP]
> Pipelines không chấp nhận một đối tượng `tqdm` làm đầu vào, nhưng bạn có thể sử dụng một trình tạo Python thay thế, dưới dạng `x for x in tqdm(...)`

### Phân loại văn bản

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

### Sinh văn bản

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

