Wróć do katalogu
Season 35 8 Odcinki 32 min 2026

Mastering Modern Pandas

v3.0 — Edycja 2026. Opanuj kluczowe abstrakcje i nowoczesne możliwości pandas 3.0 w 2026 roku. Poznaj Label Alignment, Copy-on-Write, integrację z PyArrow, zaawansowaną analizę szeregów czasowych oraz strategie skalowania dla zbiorów danych out-of-core.

Nauka o danych Analiza danych Python Core
Mastering Modern Pandas
Teraz odtwarzane
Click play to start
0:00
0:00
1
Kluczowa abstrakcja: DataFrames i Label Alignment
Zgłębiamy podstawowe modele koncepcyjne pandas: Series i DataFrame. Dowiesz się, dlaczego wbudowane wyrównywanie etykiet (Label Alignment) to kluczowa funkcja, która zapobiega katastrofom związanym z niedopasowaniem wierszy.
3m 37s
2
Rewolucja Copy-on-Write
Odkryj najbardziej znaczącą zmianę architektoniczną we współczesnym pandas: Copy-on-Write. Dowiesz się, jak CoW eliminuje nieprzewidywalne mutacje i optymalizuje zużycie pamięci.
3m 43s
3
Maszynownia PyArrow
Pandas nie opiera się już wyłącznie na NumPy. Dowiesz się, jak wykorzystać backend PyArrow do natywnej obsługi brakujących danych i niesamowitej oszczędności pamięci w przypadku ciągów znaków.
4m 27s
4
Nowoczesne wczytywanie danych
Omawiamy wydajne strategie wejścia/wyjścia (I/O) dla dużych zbiorów danych. Dowiesz się, jak selektywnie wczytywać ogromne pliki bezpośrednio do wysoce zoptymalizowanych struktur pamięci.
3m 41s
5
Algebra relacyjna: Merge i Join
Badamy, jak łączyć rozproszone zbiory danych za pomocą algebry relacyjnej. Dowiesz się, jak wykonywać zoptymalizowane złączenia w stylu SQL bezpośrednio w pandas.
4m 03s
6
Wzorzec Split-Apply-Combine
Odblokuj prawdziwą moc obiektu GroupBy. Dowiesz się, jak wyjść poza proste średnie, aby wykonywać złożone, specyficzne dla grup transformacje i filtrowania.
3m 46s
7
Mistrzostwo w szeregach czasowych
Zagłębiamy się w bezdyskusyjną dominację pandas w analizie szeregów czasowych. Dowiesz się, jak wykorzystać DatetimeIndex i natywny resampling dla danych o wysokiej częstotliwości.
4m 37s
8
Skalowanie do zbiorów danych Out-of-Core
Mierzymy się z ograniczeniami pamięci RAM twojego komputera. Dowiesz się, jak przetwarzać zbiory danych znacznie większe niż dostępna pamięć, używając wyłącznie chunkingu w pandas.
4m 08s

Odcinki

1

Kluczowa abstrakcja: DataFrames i Label Alignment

3m 37s

Zgłębiamy podstawowe modele koncepcyjne pandas: Series i DataFrame. Dowiesz się, dlaczego wbudowane wyrównywanie etykiet (Label Alignment) to kluczowa funkcja, która zapobiega katastrofom związanym z niedopasowaniem wierszy.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Mastering Modern Pandas, odcinek 1 z 8. Pobierasz dwie kolumny danych finansowych, dodajesz je do siebie, a ostateczna suma nie ma sensu. Wiersze się przesunęły, a ty właśnie dodałeś wczorajszą cenę zamknięcia do dzisiejszego wolumenu. Dzieje się tak, gdy traktujesz dane jak zwykłą siatkę, zamiast polegać na kluczowej abstrakcji: DataFrame'ach i Label Alignment. Ludzie często patrzą na pandas i myślą, że to po prostu programowalny arkusz kalkulacyjny albo standardowy, dwuwymiarowy NumPy array. Wcale tak nie jest. Zwykły NumPy array opiera się na ścisłym indeksowaniu pozycyjnym. Jeśli dodasz do siebie dwa arraye, element na pozycji zero dodaje się do elementu na pozycji zero. Jeśli w twoich danych brakuje wiersza, wszystko się przesuwa, a twoje obliczenia po cichu się psują. Pandas rozwiązuje dokładnie ten problem, oddzielając dane od ich fizycznej pozycji w pamięci. Wykorzystuje wbudowane wyrównywanie danych, co oznacza, że dopasowuje dane po labelach, a nigdy po pozycji. Aby to zrozumieć, spójrz na fundament tej biblioteki, czyli Series. Series to jednowymiarowy array, który może przechowywać dowolny typ danych. W przeciwieństwie do standardowej listy, każdy element w Series jest na sztywno przypięty do labela. Te labele razem tworzą to, co pandas nazywa indexem. Możesz używać integerów jako labeli, ale częściej używasz stringów lub timestampów. DataFrame to po prostu zbiór tych obiektów Series działających jako kolumny, które współdzielą ten sam index i siedzą obok siebie. I tu jest sedno. Kiedy wykonujesz operację w pandas, to index dyktuje zachowanie. Powiedzmy, że masz dwa obiekty Series z dziennymi zwrotami z akcji. Series A ma dane z poniedziałku, wtorku, środy i czwartku. Series B ma dane ze środy, czwartku i piątku. Jeśli każesz pandas dodać do siebie te dwa obiekty Series, zignoruje on ich fizyczną kolejność. Patrzy na labele z datami. Znajduje środę w Series A i dodaje ją do środy w Series B, mimo że środa jest trzecim elementem w pierwszym zbiorze danych, a w drugim jest na samym początku. To prowadzi do problemu dni, które się nie pokrywają. Poniedziałek istnieje w pierwszym Series, ale nie w drugim. Piątek istnieje w drugim, ale nie w pierwszym. Pandas nie crashuje i na pewno nie zgaduje wartości. Zamiast tego tworzy nowy index, który jest unią wszystkich labeli z obu wejść. Dla każdego labela, który nie istnieje w obu miejscach, pandas wstawia NaN, czyli Not a Number. Operacja kończy się sukcesem, a ty od razu widzisz, gdzie twoje dane są niekompletne. Nigdy nie musisz pisać loopa, żeby sprawdzić, czy daty się zgadzają. Wyrównywanie jest automatyczne, wbudowane bezpośrednio w samą strukturę danych. Ta sama logika skaluje się bezpośrednio do DataFrame'ów. DataFrame wyrównuje się w obu wymiarach jednocześnie. Kiedy operujesz na dwóch DataFrame'ach, pandas dopasowuje label wiersza do labela wiersza, a nazwę kolumny do nazwy kolumny. Idealnie wyrównuje całą strukturę, zanim wykona pojedynczą operację matematyczną. Wszystko, co nie pokrywa się w wierszach i kolumnach, zostaje oznaczone jako brakujące dane. Prawdziwą siłą pandas nie jest matematyka, którą wykonuje, ale fakt, że label zawsze podróżuje razem z danymi, co sprawia, że niedopasowania pozycyjne są strukturalnie niemożliwe. Jeśli chcesz wesprzeć nasz podcast, znajdziesz nas, szukając DevStoriesEU na platformie Patreon. Dzięki za wysłuchanie, miłego kodowania wszystkim!
2

Rewolucja Copy-on-Write

3m 43s

Odkryj najbardziej znaczącą zmianę architektoniczną we współczesnym pandas: Copy-on-Write. Dowiesz się, jak CoW eliminuje nieprzewidywalne mutacje i optymalizuje zużycie pamięci.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Mastering Modern Pandas, odcinek 2 z 8. Wyciągasz slice swoich danych, aktualizujesz pojedynczą wartość i nagle twój oryginalny dataset jest uszkodzony. Albo co gorsza, dostajesz nieprzewidywalny warning i nie masz pojęcia, czy twój update faktycznie dotyczył slice'a, czy źródła. Wersja 3.0 w końcu rozwiązuje ten chaos, czyniąc Copy-on-Write domyślnym zachowaniem. Copy-on-Write fundamentalnie zmienia sposób, w jaki pandas zarządza pamięcią. We wcześniejszych wersjach pandas często robił defensywne kopie, żeby zapobiec przypadkowej modyfikacji oryginalnego datasetu. Jeśli filtrowałeś dataset, pandas go kopiował. Jeśli usuwałeś kolumnę, pandas kopiował resztę. To marnowało ogromne ilości pamięci i cykli procesora. Kiedy nie kopiował, zwracał view, co oznaczało, że modyfikacja nowego obiektu po cichu zmieniała parenta. Z Copy-on-Write, każdy DataFrame lub Series pochodzący od innego, współdzieli dokładnie tę samą pamięć pod spodem. To oznacza, że wyciągnięcie subsetu, usunięcie kolumny czy zresetowanie indeksu jest niemal natychmiastowe. Żadne dane nie są duplikowane z góry. Oto kluczowa sprawa. Nie myl legacy view z Copy-on-Write lazy copy. W tradycyjnym view, zarówno parent, jak i child wskazują na tę samą pamięć, a zmiana w jednym zmienia drugie. Copy-on-Write działa inaczej. Współdzielona pamięć jest tymczasowa i ściśle chroniona. Współdzielenie trwa tylko do momentu, aż spróbujesz coś zmienić. Weźmy konkretny scenariusz. Masz DataFrame zawierający profile użytkowników. Wybierasz kolumnę age i przypisujesz ją do nowej zmiennej o nazwie age subset. W tym dokładnie momencie, age subset zajmuje zero dodatkowej pamięci. Wskazuje bezpośrednio na oryginalny DataFrame z profilami użytkowników. Następnie aktualizujesz pierwszą wartość w swoim age subset na dziewięćdziesiąt dziewięć. I w tym miejscu dzieje się część write z Copy-on-Write. Pandas wykrywa modyfikację. Przed wykonaniem twojego update'u sprawdza, czy jakikolwiek inny obiekt współdzieli ten konkretny blok danych. Ponieważ parent DataFrame nadal go używa, pandas natychmiast alokuje nową pamięć, kopiuje tam dane, a następnie zapisuje wartość dziewięćdziesiąt dziewięć w nowej lokalizacji. Twój parent DataFrame pozostaje bezpiecznie niezmieniony. Mutowanie subsetu nigdy nie mutuje parenta. Ten mechanizm idealnie kaskaduje się przez chained operations. Kiedy łączysz ze sobą operacje, takie jak usuwanie pustych wierszy, zastępowanie wartości i zmiana nazw kolumn, starsze wersje pandas tworzyły fizyczną kopię na każdym pojedynczym kroku. Z Copy-on-Write, te pośrednie kroki po prostu współdzielą pamięć. Fizyczna kopia jest triggerowana tylko wtedy, gdy dany krok faktycznie mutuje tablice danych pod spodem. Jeśli operacja tylko przestawia referencje, żadna kopia nie ma miejsca. To całkowicie eliminuje przypadkowe uszkodzenie danych. Nie musisz już zgadywać, czy operacja zwróciła view, czy kopię, i już nigdy więcej nie zobaczysz warningu Setting With Copy. Zasada jest absolutna: obiekty parent i child nigdy nie będą się wzajemnie modyfikować. Odkładając kopie do dokładnej milisekundy, w której następuje modyfikacja, pandas daje ci wysoką wydajność i niski memory footprint charakterystyczny dla views, w połączeniu ze ścisłym bezpieczeństwem deep copies. To wszystko w tym odcinku. Dzięki za słuchanie i twórz dalej!
3

Maszynownia PyArrow

4m 27s

Pandas nie opiera się już wyłącznie na NumPy. Dowiesz się, jak wykorzystać backend PyArrow do natywnej obsługi brakujących danych i niesamowitej oszczędności pamięci w przypadku ciągów znaków.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Mastering Modern Pandas, odcinek 3 z 8. Ładujesz dataset z kilkoma milionami wierszy i nagle zużycie pamięci wystrzeliwuje w kosmos. Liczby są w porządku, ale kolumny tekstowe i brakujące wartości po cichu zżerają twój RAM. Rozwiązaniem jest fundamentalna zmiana sposobu, w jaki pandas przechowuje dane, i dokładnie o tym jest ten odcinek: silnik PyArrow. Jeśli słyszałeś o Apache Arrow, możesz myśleć, że to rzecz wyłącznie do dużych systemów rozproszonych, takich jak Spark czy Hadoop. Wcale tak nie jest. Arrow to teraz pełnoprawny, natywny format pamięci i execution engine wbudowany prosto w pandas. Przez lata pandas opierał się wyłącznie na NumPy. NumPy jest niesamowicie szybki w gęstych obliczeniach numerycznych, ale ma ogromny martwy punkt, jeśli chodzi o brakujące dane. NumPy nie ma natywnego konceptu brakującego integera ani brakującego booleana. Jeśli masz kolumnę z integerami i brakuje w niej pojedynczej wartości, pandas historycznie był zmuszony do konwersji całej kolumny na floaty, tylko po to, by móc użyć znacznika Not a Number. To zmienia twoje typy danych, psuje dokładne dopasowania i zżera więcej pamięci. PyArrow rozwiązuje ten problem za pomocą validity bitmap. Zamiast zmieniać typ danych, żeby pomieścić brakującą wartość, Arrow zostawia twoje integery jako integery. Dodaje ukryty, mocno skompresowany array jedynek i zer obok twoich danych. Jedynka oznacza, że wartość jest poprawna. Zero oznacza, że jej brakuje. Twój typ danych pozostaje nienaruszony, a śledzenie brakujących wartości kosztuje prawie zero pamięci. I tu jest kluczowa sprawa. Oszczędności pamięci są jeszcze bardziej ekstremalne, gdy mamy do czynienia z tekstem. Tradycyjnie pandas przechowuje stringi używając typu danych object z NumPy. To oznacza, że kolumna tak naprawdę nie trzyma twojego tekstu. Trzyma wskaźniki do pamięci. Każdy wiersz wskazuje na standardowy obiekt string w Pythonie, rozsiany gdzieś indziej w pamięci twojego komputera. Jeśli masz dziesięć milionów wierszy tekstu, masz dziesięć milionów wskaźników i dziesięć milionów oddzielnych obiektów typu string. Overhead pamięciowy jest przytłaczający, a iterowanie po nich jest potwornie wolne. PyArrow całkowicie zmienia tę architekturę. Kiedy ustawisz swoje kolumny w pandas tak, by używały typu danych string z PyArrow, tekst jest przechowywany w pojedynczym, ciągłym bloku pamięci. Kolumna śledzi jedynie byte offsets. Zapisuje dokładnie, gdzie każde słowo się zaczyna i kończy w tym wielkim, ciągłym bloku. Wyobraź sobie dataset o wysokiej kardynalności. Masz kolumnę ze stringami user agent albo unikalnymi ID transakcji. Wiele wierszy jest pustych. Jeśli wczytasz to do pandas w tradycyjny sposób, domyślnie dostaniesz array typu object z NumPy. Teraz powiedz pandas, żeby zamiast tego użył silnika PyArrow, jawnie przypisując typ danych string oparty na PyArrow podczas kroku odczytu. Natychmiast memory footprint spada, często o pięćdziesiąt procent lub więcej. Ta poprawa wykracza poza same limity RAM-u. Ponieważ dane są teraz ciasno upakowane w strukturze stworzonej do analityki, operacje string matching znacznie przyspieszają. Jeśli odpalisz wyszukiwanie regular expression na tej kolumnie, silnik Arrow przetworzy surowe bajty bezpośrednio na poziomie systemu. Całkowicie omija to powolny overhead obiektów w Pythonie. Dostajesz kolumny z integerami, które faktycznie zostają integerami, gdy brakuje danych, oraz operacje na stringach, które nie dławią twojego sprzętu. Jeśli przetwarzasz tekst lub brudne dane, poleganie na arrayu typu object z NumPy jest już przestarzałe. Używanie typów danych opartych na PyArrow to najszybszy sposób, żeby ciężki pipeline w pandas stał się natychmiast lżejszy. Dzięki za wysłuchanie, happy coding wszystkim!
4

Nowoczesne wczytywanie danych

3m 41s

Omawiamy wydajne strategie wejścia/wyjścia (I/O) dla dużych zbiorów danych. Dowiesz się, jak selektywnie wczytywać ogromne pliki bezpośrednio do wysoce zoptymalizowanych struktur pamięci.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Mastering Modern Pandas, odcinek 4 z 8. Masz wielogigabajtowy plik Parquet z setką kolumn. Do uruchomienia metryk potrzebujesz tylko czterech z nich. Jeśli twoim pierwszym krokiem jest załadowanie całego pliku do dataframe'u, a następnie odfiltrowanie kolumn, marnujesz ogromne ilości pamięci RAM i cykli CPU, zanim jeszcze rozpoczniesz analizę. Rozwiązaniem jest opanowanie Modern Data Ingestion. Głównym wąskim gardłem w data ingestion jest dyskowe I/O. Funkcje read w Pandas, takie jak read underscore csv i read underscore parquet, skanują dane z dysku do pamięci. Aby zminimalizować ten transfer, używasz argumentu o nazwie usecols. Przekazujesz listę zawierającą dokładne nazwy kolumn, których potrzebujesz. Parser odczytuje z pliku tylko te konkretne kolumny. Wzrost wydajności, jaki osiągniesz, zależy w dużej mierze od formatu pliku. Pliki CSV przechowują dane wiersz po wierszu. Kiedy używasz usecols z plikiem CSV, parser nadal musi przeskanować cały plik tekstowy wiersz po wierszu, ale natychmiast odrzuca niepotrzebne kolumny przed alokacją pamięci dla dataframe'u. Pliki Parquet przechowują jednak dane kolumna po kolumnie. W przypadku stukolumnowego pliku Parquet, gdzie potrzebujesz tylko czterech kolumn z metrykami, przekazanie usecols oznacza, że parser całkowicie ignoruje bloki pliku zawierające pozostałe dziewięćdziesiąt sześć kolumn. Odczytuje z dysku tylko te bajty, których absolutnie potrzebuje. To drastycznie zmniejsza zarówno twój czas odczytu, jak i memory footprint. Ograniczenie liczby kolumn to tylko pierwszy krok. Kolejna optymalizacja dotyczy sposobu, w jaki Pandas przechowuje te kolumny w pamięci. Historycznie Pandas opierał się wyłącznie na arrayach NumPy. NumPy doskonale nadaje się do gęstych obliczeń numerycznych, ale ma problemy z danymi tekstowymi i brakującymi wartościami. Przechowuje stringi jako rozproszone obiekty Pythona w pamięci i wymusza konwersję kolumn typu integer na float, tylko po to, by reprezentować brakujące dane. Aby rozwiązać ten problem, Pandas wprowadził argument dtype backend. Kiedy ustawisz ten argument na string pyarrow, Pandas użyje Apache Arrow jako backendu dla twoich danych. Arrow przechowuje stringi w wysoce wydajnych, ciągłych blokach pamięci i używa oddzielnej bitmaski do śledzenia brakujących wartości, pozostawiając twoje integery w nienaruszonym stanie. Oto kluczowa kwestia. Możesz pomyśleć, że Pandas najpierw wczytuje dane do arrayów NumPy, a następnie konwertuje je na Arrow. Tak się jednak nie dzieje. Kiedy wskażesz backend PyArrow w funkcji read, Pandas całkowicie pomija NumPy podczas fazy parsowania. Dane płyną prosto z pliku na dysku do arrayów PyArrow w pamięci. Pozwala to uniknąć poważnego spadku wydajności związanego z pośrednimi alokacjami pamięci. Spójrzmy na pełny pipeline. Wywołujesz read underscore parquet. Najpierw przekazujesz ścieżkę do pliku. Po drugie, przekazujesz usecols z listą twoich czterech kolumn z metrykami. Po trzecie, ustawiasz argument dtype backend na pyarrow. Parser przeskakuje bezpośrednio do czterech kolumn na dysku, wyciąga je i streamuje prosto do pamięci z backendem Arrow. W rezultacie otrzymujesz lekki, błyskawiczny dataframe, który zawiera dokładnie to, czego potrzebujesz, oparty na nowoczesnych typach danych. Filtrowanie kolumn w warstwie IO zamiast w warstwie aplikacji to najskuteczniejszy sposób na zapobieganie crashom out-of-memory w Pandas. To wszystko w tym odcinku. Dzięki za wysłuchanie i twórz dalej!
5

Algebra relacyjna: Merge i Join

4m 03s

Badamy, jak łączyć rozproszone zbiory danych za pomocą algebry relacyjnej. Dowiesz się, jak wykonywać zoptymalizowane złączenia w stylu SQL bezpośrednio w pandas.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Mastering Modern Pandas, odcinek 5 z 8. Masz listę dziesięciu milionów transakcji, a każda z nich ma tylko customer ID. Potrzebujesz rzeczywistych nazw klientów przypisanych do tych transakcji. Jeśli piszesz pętlę w Pythonie albo używasz dictionary mapping, żeby dopasować te ID do nazw, marnujesz cykle CPU i pamięć. Pandas ma zoptymalizowany silnik stworzony specjalnie do operacji w stylu SQL w jednej linijce. Dzisiaj porozmawiamy o algebrze relacyjnej: Merge i Join. Zanim przejdziemy dalej, wyjaśnijmy częste nieporozumienie. Ludzie często mylą merge z concatenation. Concatenation to po prostu fizyczne układanie arrays jedna na drugiej lub obok siebie. Merge to zupełnie co innego. Merge służy do joinów w relacyjnych bazach danych. Dopasowuje wiersze z dwóch różnych tabel na podstawie wartości wspólnych kluczy. Podstawową funkcją do tego jest pandas dot merge. Przyjmuje ona dwa DataFrames, które nazywamy lewą i prawą tabelą. Wróćmy do naszego scenariusza transakcji. Twój lewy DataFrame to ogromna fact table zawierająca miliony zakupów. Twój prawy DataFrame to mniejsza dimension table zawierająca dane klientów, takie jak imiona, nazwiska i adresy e-mail. Obie tabele współdzielą kolumnę o nazwie customer ID. Ta konkretna konfiguracja to many-to-one join. Masz wiele transakcji należących do jednego klienta. Kiedy robisz ich merge za pomocą klucza customer ID, pandas bierze pojedynczy rekord klienta z prawej tabeli i robi broadcast na wszystkie pasujące transakcje w lewej tabeli. Oto kluczowa informacja. Najważniejszym parametrem, który kontrolujesz, jest argument how. Określa on, które klucze przetrwają merge i znajdą się w końcowym wyniku. Domyślnie pandas używa inner join. Jeśli nie podasz argumentu how, wynik zachowa tylko wiersze, w których customer ID występuje w obu tabelach. Jeśli klient dokonał transakcji, ale jego rekord został usunięty z bazy danych klientów, ta transakcja całkowicie zniknie z twojego wyniku po operacji merge. Aby zapobiec utracie danych z głównej tabeli, używasz left join. Przekazując left do argumentu how, pandas zachowuje każdy pojedynczy wiersz z lewej tabeli, czyli twojej ogromnej listy transakcji. Jeśli transakcja ma customer ID, który nie istnieje w prawej tabeli, pandas nadal zachowuje wiersz transakcji, ale wypełnia brakujące dane klienta wartościami Not a Number. To jest dokładnie ta logika, której potrzebujesz, dołączając szczegóły z dimension table do głównej fact table. Dokładnym przeciwieństwem jest right join. Przekazanie right zachowuje wszystkie wiersze z customer dimension table, niezależnie od tego, czy mają one pasujące transakcje w lewej tabeli. W rezultacie otrzymujesz listę wszystkich klientów, a ci, którzy nic nie kupili, po prostu mają brakujące wartości w danych transakcji. Na koniec mamy outer join. Przekaż outer do argumentu how, a pandas zachowa wszystko. Robi unię kluczy z obu DataFrames. Każda transakcja i każdy klient trafiają do ostatecznego datasetu, a brakujące wartości wypełniają luki wszędzie tam, gdzie nie znaleziono idealnego dopasowania. Domyślny inner join po cichu usuwa niedopasowane dane, więc o ile nie chcesz jawnie odfiltrować wierszy, zawsze powinieneś określić left join podczas dołączania lookup tables do swojego głównego datasetu. To wszystko w tym odcinku. Dzięki za wysłuchanie i budujcie dalej!
6

Wzorzec Split-Apply-Combine

3m 46s

Odblokuj prawdziwą moc obiektu GroupBy. Dowiesz się, jak wyjść poza proste średnie, aby wykonywać złożone, specyficzne dla grup transformacje i filtrowania.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Mastering Modern Pandas, odcinek 6 z 8. Pewnie myślisz, że grupowanie danych polega po prostu na podsumowywaniu liczb, żeby wyliczyć sumę albo średnią. Ale co, jeśli musisz ocenić pojedynczy wiersz na podstawie zachowania grupy, do której należy, bez utraty oryginalnego kształtu twojego datasetu? To wymaga wyjścia poza proste podsumowania i użycia wzorca split-apply-combine. Kiedy wywołujesz metodę groupby w pandas, odpalasz sekwencyjny, trzyetapowy proces. Pierwszy to split. Pandas bierze twój cały dataset i dzieli go na niezależne grupy na podstawie podanego przez ciebie klucza. Kolejny to krok apply, w którym funkcja jest wykonywana na każdej grupie, całkowicie niezależnie od pozostałych. Na koniec krok combine bierze wyniki z każdej grupy i zszywa je z powrotem w jedną strukturę danych. Wielu developerów uważa, że krok apply służy wyłącznie do agregacji. Agregacja bierze grupę wartości i zwraca pojedynczą liczbę, taką jak suma czy średnia. Jeśli zgrupujesz dataset z obsługi klienta po agencie i poprosisz o średni czas rozwiązania problemu, dostaniesz nowy dataset z jednym wierszem na agenta. To przydatne, ale to tylko jedna trzecia całej historii. Oto kluczowa sprawa. Krok apply jest równie często używany do transformacji i filtracji. Transformacja wykonuje obliczenia na grupie, ale zwraca obiekt, który jest indeksowany dokładnie tak samo jak oryginalne dane. Nie zmniejsza liczby wierszy. Wróćmy do naszego datasetu z obsługi klienta. Chcesz wiedzieć, czy rozwiązanie konkretnego ticketu zajęło nietypowo dużo czasu. Ale nietypowy czas dla juniora może być normalnym czasem dla seniora, który zajmuje się bardzo złożonymi problemami. Potrzebujesz z-score czasu rozwiązania, odniesionego tylko do historycznej średniej tego konkretnego agenta. Robisz split danych po agencie i robisz apply funkcji transformacji, która oblicza z-score. Pandas oblicza średnią i odchylenie standardowe dla agenta A, standaryzuje tickety agenta A, robi dokładnie to samo dla agenta B, a następnie robi combine. Dostajesz z powrotem swój oryginalny dataset, wiersz po wierszu, ale teraz każdy ticket ma ustandaryzowany wynik oparty ściśle na kontekście jego konkretnej grupy. Trzecie kluczowe zastosowanie to filtracja. Pozwala to odrzucać całe grupy na podstawie ich wspólnej właściwości, zamiast oceniać pojedyncze wiersze. Załóżmy, że chcesz przeanalizować te z-score'y ticketów, ale niektórzy agenci w twoim datasecie przetworzyli tylko dwa lub trzy tickety. Ich średnie nie mają statystycznego znaczenia. Możesz użyć funkcji filtrującej na zgrupowanym obiekcie, żeby sprawdzić rozmiar każdej grupy. Jeśli grupa ma mniej niż dziesięć ticketów, logika filtra zwraca false, a pandas usuwa każdy pojedynczy wiersz należący do tego agenta. Krok combine zwraca wtedy dataset zawierający tylko tickety od agentów z odpowiednią wielkością próby. Robisz split danych po kluczu, apply reguły logicznej, która ocenia grupę, i combine tych wierszy, które przetrwały. Agregacja redukuje dane. Transformacja standaryzuje dane w ich lokalnym kontekście. Filtracja odrzuca dane na podstawie reguł grupy. Prawdziwą siłą wzorca split-apply-combine jest to, że pozwala ci manipulować pojedynczymi wierszami przy użyciu kontekstu z poziomu grupy, bez konieczności pisania ręcznej pętli. Jeśli uważasz te deep dive'y za pomocne i chcesz wesprzeć program, możesz wyszukać DevStoriesEU na Patreonie. Chciałbym poświęcić chwilę, żeby podziękować ci za słuchanie — to bardzo nam pomaga. Miłego dnia!
7

Mistrzostwo w szeregach czasowych

4m 37s

Zagłębiamy się w bezdyskusyjną dominację pandas w analizie szeregów czasowych. Dowiesz się, jak wykorzystać DatetimeIndex i natywny resampling dla danych o wysokiej częstotliwości.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Mastering Modern Pandas, odcinek 7 z 8. Ręczne pisanie własnych agregacji czasowych to koszmar z powodu brakujących interwałów, lat przestępnych i logiki dni roboczych. Jeśli piszesz customowy kod, żeby zaokrąglać surowe timestampy do regularnych bucketów, to znaczy, że niepotrzebnie utrudniasz sobie życie. Rozwiązaniem jest Time Series Mastery wykorzystujące natywne struktury temporalne w pandas. Podstawą funkcjonalności szeregów czasowych w pandas jest DatetimeIndex. Zamiast standardowych integerów jako numerów wierszy, indeks twojego dataframe'u staje się ścisłą sekwencją precyzyjnych timestampów. Zmiana indeksu na DatetimeIndex fundamentalnie zmienia sposób zachowania dataframe'u, sprawiając, że cała struktura staje się świadoma czasu. Umożliwia to natywny time-based slicing. Jeśli potrzebujesz danych tylko z października 2023 roku, przekazujesz prosty string "2023-10" do lokalizatora wierszy. Pandas automatycznie oblicza dokładne granice co do mikrosekundy dla tego miesiąca i zwraca poprawny subset. Możesz przekazywać częściowe stringi z datą z dokładnością do godziny lub minuty, a indeks sam rozwiązuje pod spodem całą matematykę na timestampach. Kiedy twoje dane są już świadome czasu, zazwyczaj musisz je zagregować. Wielu developerów myli time-based resampling z podstawowym grupowaniem. Próbują aplikować standardowe operacje group-by na kolumnie z datą. Takie podejście zawodzi, gdy masz do czynienia z rzeczywistymi, chaotycznymi szeregami czasowymi. Standardowe grupowanie patrzy tylko na jawne wiersze, które są aktualnie obecne w twoim dataframe'ie. Jeśli serwer padnie na godzinę, standardowa operacja group-by po prostu całkowicie pomija tę godzinę. Twój wyjściowy timeline będzie miał ukrytą lukę, co zepsuje wszelkie późniejsze obliczenia oparte na czasie. I tu jest kluczowa sprawa. Metoda kropka resample jest fundamentalnie inna, ponieważ natywnie rozumie logikę kalendarza. Nakłada ona sztywną, ciągłą siatkę czasu na twoje dane. Jeśli robisz resample w dziesięciominutowych interwałach i żadne dane nie pojawią się w konkretnym dziesięciominutowym oknie, pandas i tak wygeneruje ten bucket. Zostawia wartości puste, zachowując ścisłą matematyczną integralność twojego timeline'u. Resampling z natury rozumie puste interwały, nieregularne długości miesięcy oraz kalendarze dni roboczych, które wykluczają weekendy i święta. Wyobraź sobie scenariusz analityka ilościowego przetwarzającego dane tradingowe. Otrzymujesz dane tickowe o wysokiej częstotliwości z giełdy. Poszczególne transakcje spływają w zupełnie nieregularnych interwałach, czasem trzy na mikrosekundę, a czasem żadna przez dwadzieścia sekund. Twój model cenowy nie jest w stanie ogarnąć tego chaosu. Wymaga idealnie wyrównanych pięciominutowych barów. Ponieważ twoje ceny transakcji są zmapowane na DatetimeIndex, wywołujesz metodę kropka resample na swoim dataframe'ie i przekazujesz string z częstotliwością "5min". To mapuje każdy nieregularny tick na ścisłą pięciominutową siatkę. Żeby zasilić model finansowy, potrzebujesz konkretnie cen Open, High, Low i Close dla każdego bucketu. Zamiast pisać customowe funkcje do wyciągania pierwszej, maksymalnej, minimalnej i ostatniej transakcji z każdego okna, chainujesz metodę kropka ohlc bezpośrednio do swojego wywołania resample. Pandas oblicza wszystkie cztery metryki naraz, zwracając czysto ustrukturyzowany dataset pięciominutowych barów. Te puste interwały, o których wspominaliśmy wcześniej, pozostają nienaruszone w tym outpucie. Następnie możesz zchainować kolejną metodę, żeby zrobić forward-fill poprzednich cen zamknięcia w puste luki, upewniając się, że twój model zawsze ma poprawne dane. Resampling przekształca nieregularne, event-driven rekordy w przewidywalny, matematycznie poprawny timeline, bez konieczności pisania ani jednej linijki logiki kalendarza. Dzięki za wysłuchanie. Do następnego razu!
8

Skalowanie do zbiorów danych Out-of-Core

4m 08s

Mierzymy się z ograniczeniami pamięci RAM twojego komputera. Dowiesz się, jak przetwarzać zbiory danych znacznie większe niż dostępna pamięć, używając wyłącznie chunkingu w pandas.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Mastering Modern Pandas, odcinek 8 z 8. Zanim postawisz potężną instancję w chmurze albo sięgniesz po rozproszony klaster obliczeniowy, możesz się zdziwić, że terabajty danych da się przetwarzać bezpośrednio na twoim laptopie. Większość błędów out-of-memory wcale nie wymaga nowego frameworka, a jedynie zmiany sposobu, w jaki czytasz pliki. Dzisiaj omówimy skalowanie do datasetów out-of-core. Przetwarzanie out-of-core oznacza po prostu pracę z datasetami, które są większe niż dostępna pamięć systemowa. Częstą reakcją na crash typu out-of-memory jest założenie, że pandas osiągnął swój twardy limit. Ludzie często od razu rzucają się do przepisywania swoich pipeline'ów w PySparku lub Dasku. Ale pandas potrafi natywnie obsłużyć ogromne ilości danych, jeśli tylko przestaniesz próbować ładować cały dataset do RAM-u za jednym zamachem. Proste wzorce z użyciem generatorów rozwiązują zdecydowaną większość tych problemów ze skalowaniem. Głównym mechanizmem przetwarzania out-of-core jest chunking. Jeśli masz do czynienia z pojedynczym, ogromnym plikiem tekstowym, standardowa funkcja read przyjmuje argument chunk size. Kiedy podasz ten argument, pandas przestaje zwracać DataFrame. Zamiast tego zwraca iterator. Za każdym razem, gdy twój kod przesuwa iterator, pandas czyta z dysku tylko określoną liczbę wierszy i zwraca je jako normalny DataFrame. Aplikujesz swoją logikę do tego chunka, wyciągasz wynik i pozbywasz się chunka z pamięci. Ponieważ stare dane są usuwane z pamięci przed wczytaniem kolejnego batcha, twoje zużycie pamięci pozostaje całkowicie płaskie, niezależnie od tego, jak duży jest plik źródłowy. I tu robi się ciekawie. Nowoczesna infrastruktura danych rzadko opiera się na pojedynczych, gigantycznych plikach tekstowych. Zazwyczaj duże datasety są przechowywane jako katalogi zawierające setki mniejszych, spartycjonowanych plików, najczęściej w formacie binarnym, takim jak Parquet. Pliki Parquet są mocno skompresowane i ładują się bardzo szybko, ale nadal nie załadujesz pięćdziesięciu gigabajtów plików Parquet do szesnastu gigabajtów RAM-u. Żeby to obsłużyć, musisz ręcznie zastosować koncepcję chunkingu na poziomie plików. Wyobraź sobie, że masz katalog z rocznymi plikami Parquet i chcesz obliczyć całkowitą częstotliwość kategorii w całym historycznym datasecie. Konstruujesz prostą pętlę iteracyjną. Najpierw zainicjalizuj pusty obiekt Series w pandas. Posłuży on jako twój akumulator dla globalnych sum. Następnie iteruj po swoim katalogu, plik po pliku. Wewnątrz pętli wczytaj obecny plik do DataFrame'a. Teraz odpal funkcję value counts na konkretnej kolumnie, którą analizujesz. To da ci obiekt Series zawierający częstotliwości tylko dla tego konkretnego roku. Kluczowym krokiem jest połączenie tego lokalnego wyniku z twoim globalnym akumulatorem. Robisz to, wywołując metodę add na twoim globalnym obiekcie Series i przekazując do niej ten lokalny Series. Ponieważ niektóre kategorie mogą istnieć w jednym pliku, ale w innym już nie, musisz ustawić argument fill value na zero. To gwarantuje, że pandas poprawnie wyrówna indeksy i doda zliczenia bez wprowadzania brakujących wartości. Kiedy pętla skończy przetwarzać ten plik, przechodzi do następnego. Python automatycznie robi garbage collection starego DataFrame'a. W efekcie streamujesz ogromny dataset przez pamięć, jeden plik na raz, budując ciągłą, globalną agregację. W przetwarzaniu out-of-core nie chodzi o to, żeby rzucać w problem nowym sprzętem. Chodzi o to, by twój aktywny stan był mały, i o zepchnięcie matematycznych agregacji w dół, do poziomu pojedynczego chunka. Ponieważ to już koniec tej serii, gorąco zachęcam cię do przejrzenia oficjalnej dokumentacji pandas na temat skalowania i wypróbowania tych wzorców w praktyce na własnych danych. Jeśli masz tematy, które chciałbyś, żebyśmy poruszyli w przyszłych seriach, wejdź na devstories dot eu i daj nam znać. Dzięki za spędzenie ze mną tych kilku minut. Do usłyszenia następnym razem, trzymaj się.