Pandas: чтение файлов Parquet / Feather
Parquet и Feather — это два эффективных колоночных формата хранения данных, предназначенных для анализа больших данных и сценариев быстрого чтения/записи. По сравнению с CSV они обеспечивают лучший коэффициент сжатия и производительность запросов.
Почему стоит использовать Parquet и Feather
Основные преимущества колоночных форматов хранения:
| Характеристика | CSV | Parquet | Feather |
|---|---|---|---|
| Формат хранения | Строчный | Колоночный | Колоночный |
| Скорость чтения | Медленная | Очень быстро | Чрезвычайно быстро |
| Скорость записи | Средняя | Высокая | Чрезвычайно быстро |
| Коэффициент сжатия | Низкая | Высокая | Средняя |
| Кроссязыковая поддержка | Общие | Java/Python/R | Python/R |
Parquet — это проект Apache Foundation, широко используемый в экосистеме больших данных (Hadoop, Spark, DuckDB и т. д.). Feather — это нативная реализация проекта Arrow, ориентированная на максимальную скорость чтения/записи.
Операции с файлами Parquet
Установка зависимостей
pip install pyarrow fastparquet
PyArrow и FastParquet — это реализации Parquet на Python. PyArrow используется по умолчанию, а FastParquet быстрее в некоторых сценариях.
Чтение файлов Parquet
Пример
# Чтение файла Parquet (по умолчанию используется pyarrow)
df = pd.read_parquet("data.parquet")
# Указать конкретный движок
df = pd.read_parquet("data.parquet", engine="pyarrow")
df = pd.read_parquet("data.parquet", engine="fastparquet")
# Чтение удалённого файла Parquet
df = pd.read_parquet("s3://bucket/data.parquet")
# Чтение определённых столбцов файла (прореживание столбцов, повышает производительность)
df = pd.read_parquet("data.parquet", columns=["name", "age", "city"])
print(df.head())
Запись файлов Parquet
Пример
# Подготовка тестовых данных
df = pd.DataFrame({
"id": range(1, 10001),
"name": ["User" + str(i) for i in range(1, 10001)],
"age": [20, 25, 30, 35] * 2500,
"city": ["Beijing", "Shanghai", "Guangzhou", "Шэньчжэнь"] * 2500,
"score": [round(i * 0.1, 2) for i in range(1, 10001)]
})
# Запись файла Parquet (по умолчанию используется движок pyarrow)
df.to_parquet("data.parquet", index=False)
# Укажите метод сжатия (snappy — быстрый, gzip — высокая степень сжатия)
df.to_parquet("data_snappy.parquet", compression="snappy", index=False)
df.to_parquet("data_gzip.parquet", compression="gzip", index=False)
df.to_parquet("data_none.parquet", compression=None, index=False) # Без сжатия
# Просмотр размера файла
import os
print("Сравнение размера файлов:")
print(f"Примерный размер исходного CSV: {len(df) * 50 / 1024 / 1024:.2f} MB")
print(f"сжатие snappy: {os.path.getsize('data_snappy.parquet') / 1024 / 1024:.2f} MB")
print(f"сжатие gzip: {os.path.getsize('data_gzip.parquet') / 1024 / 1024:.2f} MB")
print(f"Без сжатия: {os.path.getsize('data_none.parquet') / 1024 / 1024:.2f} MB")
Использование движка FastParquet
Пример
import time
# Тест производительности записи разных движков
df = pd.DataFrame({
"id": range(1, 100001),
"value": range(1, 100001)
})
# Запись с помощью движка pyarrow
start = time.time()
df.to_parquet("test_pyarrow.parquet", engine="pyarrow", compression="snappy")
print(f"время записи pyarrow: {time.time() - start:.3f}s")
# запись с использованием движка fastparquet
start = time.time()
df.to_parquet("test_fastparquet.parquet", engine="fastparquet", compression="snappy")
print(f"время записи fastparquet: {time.time() - start:.3f}s")
Операции с файлами Feather
Feather — это Python-реализация проекта Arrow, ориентированная на максимальную скорость чтения/записи в памяти.
Установка зависимостей
pip install pyarrow
Чтение файлов Feather
Пример
# Чтение файла Feather
df = pd.read_feather("data.feather")
# Чтение версии v2 файла Feather (более универсальной)
df = pd.read_feather("data.feather", version="2.0")
# Чтение определённых столбцов
df = pd.read_feather("data.feather", columns=["name", "age"])
print(df.head())
Запись файлов Feather
Пример
# Подготовка тестовых данных
df = pd.DataFrame({
"id": range(1, 10001),
"name": ["User" + str(i) for i in range(1, 10001)],
"value": [round(i * 0.1, 2) for i in range(1, 10001)]
})
# Запись файла Feather
df.to_feather("data.feather")
# Сжатие LZ4 (быстрее)
df.to_feather("data_lz4.feather", compression="lz4")
# Сжатие ZSTD (более высокий коэффициент сжатия)
df.to_feather("data_zstd.feather", compression="zstd")
# Просмотр размера файла
import os
print(f"Без сжатия: {os.path.getsize('data.feather') / 1024:.2f} KB")
print(f"LZ4: {os.path.getsize('data_lz4.feather') / 1024:.2f} KB")
print(f"ZSTD: {os.path.getsize('data_zstd.feather') / 1024:.2f} KB")
Тест сравнения производительности
Пример
import numpy as np
import time
import os
import tempfile
# Создание тестовых данных
np.random.seed(42)
n_rows = 1000000
df = pd.DataFrame({
"id": range(n_rows),
"category": np.random.choice(["A", "B", "C", "D"], n_rows),
"value": np.random.randn(n_rows),
"flag": np.random.choice([True, False], n_rows),
"date": pd.date_range("2020-01-01", periods=n_rows, freq="1min")
})
# Создание временного каталога
with tempfile.TemporaryDirectory() as tmpdir:
# Запись CSV
start = time.time()
df.to_csv(f"{tmpdir}/data.csv", index=False)
csv_write = time.time() - start
start = time.time()
df_csv = pd.read_csv(f"{tmpdir}/data.csv")
csv_read = time.time() - start
# Запись Parquet
start = time.time()
df.to_parquet(f"{tmpdir}/data.parquet", index=False)
pq_write = time.time() - start
start = time.time()
df_pq = pd.read_parquet(f"{tmpdir}/data.parquet")
pq_read = time.time() - start
# Запись Feather
start = time.time()
df.to_feather(f"{tmpdir}/data.feather")
feather_write = time.time() - start
start = time.time()
df_feather = pd.read_feather(f"{tmpdir}/data.feather")
feather_read = time.time() - start
# Вывод результатов
print(f"{'Формат':<10} {'Время записи':<12} {'Время чтения':<12} {'Размер файла':<12}")
print("-" * 50)
print(f"{'CSV':<10} {csv_write:.3f}s{'':<5} {csv_read:.3f}s{'':<5} {os.path.getsize(f'{tmpdir}/data.csv')/1024/1024:.2f}MB")
print(f"{'Parquet':<10} {pq_write:.3f}s{'':<5} {pq_read:.3f}s{'':<5} {os.path.getsize(f'{tmpdir}/data.parquet')/1024/1024:.2f}MB")
print(f"{'Feather':<10} {feather_write:.3f}s{'':<5} {feather_read:.3f}s{'':<5} {os.path.getsize(f'{tmpdir}/data.feather')/1024/1024:.2f}MB")
Сценарии использования и рекомендации по выбору
| Сценарий | Рекомендуемый формат | Причина |
|---|---|---|
| Анализ больших данных | Parquet | Высокая степень сжатия, быстрые колоночные запросы, широкая экосистема |
| Передача данных Python/R | Feather | Чрезвычайно быстрое чтение/запись, нативная поддержка Arrow |
| Интеграция со Spark/Hadoop | Parquet | Стандартный формат в экосистеме больших данных |
| Резервное копирование/архивирование данных | Parquet | Высокая степень сжатия, поддерживает эволюцию схемы |
| Кэш временных данных | Feather | Самое быстрое чтение/запись |
Часто задаваемые вопросы
1. Ошибка чтения Parquet
Убедитесь, что установлен pyarrow или fastparquet:pip install pyarrow
2. Повреждение файла
При записи убедитесь, что данные полностью записаны на диск. После записи рекомендуется проверить, что файл читается.
3. Совместимость версий
Разные версии Parquet могут иметь проблемы совместимости. Рекомендуется использовать фиксированную версию в вашем проекте.
Другие расширения