Parquet: szybki magazyn kolumnowy
Zapisuj DataFrame Pandas w formacie Parquet za pomocą to_parquet(), odczytuj go szybciej niż CSV i używaj wyboru kolumn, aby wczytywać tylko potrzebne pola.
Parquet: szybki magazyn kolumnowy to bezpłatna lekcja Pandas & NumPy Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Pandas & NumPy Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.
Czym jest Parquet?
Apache Parquet to kolumnowy binarny format plików przeznaczony do zastosowań analitycznych. W przeciwieństwie do formatu CSV, który przechowuje dane wierszami jako tekst, Parquet zapisuje każdą kolumnę w ciągłym bloku, skutecznie ją kompresuje i koduje metadane. Dzięki temu jest znacznie szybszy w przypadku zapytań odczytujących tylko kilka kolumn z szerokiej tabeli. Parquet to de facto standardowy format w jeziorach danych (AWS S3, Google Cloud Storage) i jest natywnie obsługiwany przez Pandas, Dask, Spark oraz BigQuery.
Zapisywanie danych Parquet za pomocą to_parquet()
Konwersja obiektu Pandas DataFrame do formatu Parquet wymaga wywołania jednej metody: df.to_parquet('output.parquet'). Domyślnym silnikiem jest pyarrow (instalowany za pomocą pip install pyarrow). Parquet dokładnie zachowuje typy danych kolumn — nie ma już problemu z odczytywaniem kolumn dat jako łańcuchów znaków. Obsługuje także kompresję od razu, za pomocą parametru compression; 'snappy' zapewnia szybki odczyt i zapis przy umiarkowanej kompresji, natomiast 'gzip' oferuje większą kompresję kosztem szybkości.
import pandas as pd
import numpy as np
# Create a sample DataFrame
np.random.seed(0)
df = pd.DataFrame({
'date': pd.date_range('2024-01-01', periods=100000, freq='T'),
'value': np.random.randn(100000),
'category': np.random.choice(['A', 'B', 'C'], 100000)
})
# Write to Parquet
df.to_parquet('data.parquet', index=False, compression='snappy')
print('Written to data.parquet')Odczytywanie danych Parquet za pomocą read_parquet()
pd.read_parquet('output.parquet') odczytuje plik z powrotem do obiektu DataFrame. W porównaniu z odczytem odpowiedniego pliku CSV odczytywanie Parquet jest zazwyczaj 5–10 razy szybsze w przypadku szerokich tabel z wieloma kolumnami. Typy danych są dokładnie zachowywane — daty pozostają typu datetime64, kategorie pozostają typu category, a liczby całkowite pozostają typu int32 lub int64, zgodnie z zapisem. Wnioskowanie typów nie jest potrzebne, ponieważ metadane są osadzone w pliku.
import pandas as pd
import time
# Read Parquet
start = time.time()
df = pd.read_parquet('data.parquet')
print(f'Read Parquet: {time.time()-start:.3f}s')
print(df.dtypes)
print(df.shape)Przycinanie kolumn: odczytywanie tylko potrzebnych kolumn
Największą zaletą przechowywania kolumnowego jest przycinanie kolumn: można odczytywać tylko wybrane kolumny bez skanowania reszty pliku. Do parametru columns należy przekazać listę nazw kolumn. Jeśli tabela ma 100 kolumn, każda zajmuje 100 MB, a potrzebne są tylko 3 kolumny, Parquet odczyta 3 MB zamiast 10 GB. CSV musi przeskanować każdy znak, aby wyodrębnić dowolną kolumnę. Dzięki temu Parquet idealnie nadaje się do szerokich tabel w potokach analitycznych.
import pandas as pd
# Only load the 2 columns needed for this analysis
df = pd.read_parquet('large_table.parquet',
columns=['date', 'revenue'])
print(df.columns.tolist())
print(df.shape)
print(df.memory_usage(deep=True).sum() / 1e6, 'MB loaded')Filtrowanie grup wierszy (predicate pushdown)
Parquet przechowuje statystyki (minimum/maksimum) dla każdej grupy wierszy (bloku wierszy) w stopce pliku. Po zastosowaniu filtra za pomocą parametru filters czytnik pomija całe grupy wierszy, w których filtr nie może znaleźć dopasowania — nazywa się to predicate pushdown. Na przykład filtrowanie dat w posortowanym chronologicznie pliku Parquet pomija całe bloki miesięcy znajdujące się poza zakresem i odczytuje tylko odpowiednie fragmenty. Silnik pyarrow obsługuje tę funkcję natywnie.
import pandas as pd
# Filter using predicate pushdown — row groups outside range are skipped
df = pd.read_parquet(
'time_series.parquet',
columns=['date', 'value'],
filters=[('date', '>=', '2024-06-01'),
('date', '<', '2024-07-01')]
)
print(f'Loaded {len(df):,} rows (June only)')
print(df.head())Parquet a CSV: porównanie
Oto praktyczne porównanie formatów Parquet i CSV dla zbioru danych zawierającego 10 milionów wierszy i 20 kolumn:
- Rozmiar pliku: CSV ~2 GB, Parquet (snappy) ~400 MB
- Czas odczytu (wszystkie kolumny): CSV ~15 s, Parquet ~2 s
- Czas odczytu (3 kolumny): CSV ~15 s (musi przeskanować całość), Parquet ~0,3 s
- Zachowanie typów danych: CSV traci typy danych, Parquet je zachowuje
- Odczyt przez człowieka: CSV tak, Parquet nie (format binarny)
W produkcyjnych potokach, w których dane są zapisywane raz i odczytywane wielokrotnie, Parquet jest niemal zawsze lepszym wyborem.
Partycjonowane zbiory danych Parquet
W przypadku bardzo dużych zbiorów danych Parquet obsługuje partycjonowane zbiory danych: dane są dzielone na wiele plików uporządkowanych w hierarchii katalogów według wartości kolumn. Na przykład partycjonowanie według roku i miesiąca tworzy ścieżkę data/year=2024/month=01/part.parquet. Podczas odczytu partycjonowanego zbioru danych automatycznie filtrowane są katalogi odpowiadające zapytaniu. Jest to standardowy układ w jeziorach danych, który umożliwia wydajne zapytania zakresowe na miliardach wierszy.
import pandas as pd
# Write a partitioned dataset (requires pyarrow)
df = pd.read_parquet('all_data.parquet')
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df.to_parquet(
'partitioned_data/',
partition_cols=['year', 'month'],
index=False
)
# Creates: partitioned_data/year=2024/month=1/part-0.parquet etc.Odczytywanie partycjonowanych zbiorów danych
Odczytywanie partycjonowanego katalogu Parquet jest identyczne z odczytywaniem pojedynczego pliku — Pandas (za pośrednictwem pyarrow) automatycznie wykrywa wszystkie pliki partycji. Wartości kolumny partycji są uwzględniane jako kolumny w wynikowym obiekcie DataFrame. Można także użyć filters, aby skorzystać z przycinania partycji, podczas którego całe poddrzewa katalogów są pomijane na podstawie wartości kolumny partycji. Dzięki temu odpytywanie partycjonowanego zbioru danych o rozmiarze 1 TB przypomina odczytywanie kilku MB.
import pandas as pd
# Read the entire partitioned dataset
df_all = pd.read_parquet('partitioned_data/')
print('All years:', df_all['year'].unique())
# Read only 2024 data using partition pruning
df_2024 = pd.read_parquet(
'partitioned_data/',
filters=[('year', '==', 2024)]
)
print('2024 rows:', len(df_2024))Parquet z Dask
Dask natywnie odczytuje i zapisuje dane Parquet za pomocą dd.read_parquet() oraz ddf.to_parquet(). Każdy plik w partycjonowanym katalogu Parquet staje się jedną partycją Dask, co umożliwia w pełni równoległy odczyt. Dask korzysta także z predicate pushdown, gdy określono filtry. Zapisywanie dużego wyniku Dask do partycjonowanego zbioru danych Parquet to standardowy sposób tworzenia danych wyjściowych we współczesnych potokach inżynierii danych.
import dask.dataframe as dd
# Read partitioned Parquet with Dask (each file = one partition)
ddf = dd.read_parquet('partitioned_data/',
columns=['date', 'revenue', 'region'],
filters=[('year', '==', 2024)])
# Compute aggregation in parallel
result = ddf.groupby('region')['revenue'].sum().compute()
print(result.sort_values(ascending=False))Opcje kompresji i kodowania
Parquet obsługuje wiele algorytmów kompresji i wewnętrznych schematów kodowania. Snappy (domyślny) stawia na szybkość przy umiarkowanym stopniu kompresji. Gzip pozwala uzyskać pliki mniejsze o około 30%, ale ich odczyt i zapis trwa dłużej. Zstd lepiej niż oba te algorytmy równoważy szybkość i stopień kompresji. W przypadku kolumn typu całkowitego Parquet automatycznie stosuje kodowanie różnicowe lub kodowanie słownikowe, aby dodatkowo zmniejszyć rozmiar, bez konieczności dodatkowej konfiguracji z Państwa strony.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({'id': range(500000), 'val': np.random.randn(500000)})
for comp in ['snappy', 'gzip', 'zstd']:
fname = f'data_{comp}.parquet'
df.to_parquet(fname, compression=comp, index=False)
import os
size_mb = os.path.getsize(fname) / 1e6
print(f'{comp}: {size_mb:.2f} MB')Zastępowanie CSV w potoku
Najprostszym sposobem na wdrożenie Parquet jest dodanie jednorazowego etapu konwersji na początku projektu: jednokrotnie odczytać plik CSV, oczyścić dane i rzutować typy danych, a następnie zapisać dane jako Parquet. Wszystkie kolejne uruchomienia odczytują plik Parquet zamiast pliku CSV. Zapewnia to natychmiastowe korzyści w zakresie szybkości i zajętości miejsca przy minimalnych zmianach w kodzie. W przypadku nowych danych przychodzących w formacie CSV (np. nocnych eksportów) należy dodać do potoku etap konwersji, który zapisuje dane w formacie Parquet przed rozpoczęciem analizy.
import pandas as pd
# One-time conversion
df = pd.read_csv('raw_data.csv',
parse_dates=['date'],
dtype={'category': 'category',
'amount': 'float32'})
df.to_parquet('clean_data.parquet', index=False)
# All future reads use Parquet
df_fast = pd.read_parquet('clean_data.parquet')
print('Loaded from Parquet:', df_fast.dtypes.to_dict())Szybkie sprawdzenie
Proszę sprawdzić swoją znajomość zagadnień analizy danych z tej lekcji.
Podsumowanie lekcji
W tej lekcji nauczyli się Państwo, że: to_parquet() i read_parquet() zapewniają szybszy, mniejszy i zachowujący typy danych zapis oraz odczyt plików w porównaniu z CSV, ograniczanie kolumn za pomocą parametru columns odczytuje tylko potrzebne kolumny, unikając skanowania całego pliku, a partycjonowane zbiory danych Parquet uporządkowane według wartości kolumn umożliwiają ograniczanie partycji, co usprawnia zapytania zakresowe w dużych jeziorach danych. W następnej części połączymy Pandas z relacyjnymi bazami danych za pomocą SQLAlchemy.
Często zadawane pytania
Czy lekcja „Parquet: szybki magazyn kolumnowy” jest bezpłatna?
Tak — pełny tekst „Parquet: szybki magazyn kolumnowy” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Pandas & NumPy Academy, przejdź na CoddyKit PRO. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Parquet: szybki magazyn kolumnowy”?
Zapisuj DataFrame Pandas w formacie Parquet za pomocą to_parquet(), odczytuj go szybciej niż CSV i używaj wyboru kolumn, aby wczytywać tylko potrzebne pola. Ćwiczysz Pandas & NumPy Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Pandas & NumPy Academy?
Nie wymagamy żadnego doświadczenia. Pandas & NumPy Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Parquet: szybki magazyn kolumnowy”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Pandas & NumPy Academy?
Tak. Każda lekcja Pandas & NumPy Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Strumieniowy odczyt CSV z chunksize
- Przyrostowa agregacja między porcjami
- Wprowadzenie do obiektów Dask DataFrame
- Parquet: szybki magazyn kolumnowy