Przez wiele miesięcy próbowałem znaleźć odpowiedź na to pytanie, ucząc się pand. Używam SAS do mojej codziennej pracy i jest świetny, ponieważ zapewnia wsparcie poza rdzeniem. Jednak SAS jest okropny jako oprogramowanie z wielu innych powodów.
Pewnego dnia mam nadzieję, że zastąpię korzystanie z SAS pythonem i pandami, ale obecnie brakuje mi nieszablonowego przepływu pracy dla dużych zestawów danych. Nie mówię o „dużych danych”, które wymagają sieci rozproszonej, ale raczej o plikach zbyt dużych, aby zmieściły się w pamięci, ale wystarczająco małych, aby zmieściły się na dysku twardym.
Moją pierwszą myślą jest HDFStore
przechowywanie dużych zestawów danych na dysku i pobieranie tylko potrzebnych elementów do ramek danych do analizy. Inni wspominali MongoDB jako łatwiejszą w użyciu alternatywę. Moje pytanie brzmi:
Jakie są najlepsze praktyki dla realizacji następujących celów:
- Ładowanie płaskich plików do stałej struktury bazy danych na dysku
- Zapytanie do tej bazy danych w celu pobrania danych do struktury danych pandy
- Aktualizacja bazy danych po manipulowaniu elementami w pandach
Przykłady z prawdziwego świata byłyby bardzo mile widziane, zwłaszcza od każdego, kto używa pand na „dużych danych”.
Edytuj - przykład tego, jak chciałbym, aby to działało:
- Iteracyjnie importuj duży plik płaski i przechowuj go w stałej strukturze bazy danych na dysku. Te pliki są zwykle zbyt duże, aby zmieścić się w pamięci.
- Aby korzystać z Pand, chciałbym przeczytać podzbiory tych danych (zwykle tylko kilka kolumn jednocześnie), które mogą zmieścić się w pamięci.
- Chciałbym utworzyć nowe kolumny, wykonując różne operacje na wybranych kolumnach.
- Musiałbym wtedy dołączyć te nowe kolumny do struktury bazy danych.
Próbuję znaleźć najlepszy sposób wykonywania tych kroków. Czytanie linków o pandach i pytaniach wydaje się, że dodanie nowej kolumny może być problemem.
Edycja - Odpowiadając w szczególności na pytania Jeffa:
- Buduję modele ryzyka kredytowego konsumentów. Rodzaje danych obejmują cechy telefonu, SSN i adresu; wartości nieruchomości; obraźliwe informacje, takie jak rejestry kryminalne, bankructwa itp. ... Zestawy danych, z których korzystam na co dzień, mają średnio prawie 1000 do 2000 pól o mieszanych typach danych: ciągłe, nominalne i porządkowe zmiennych danych liczbowych i znaków. Rzadko dołączam wiersze, ale wykonuję wiele operacji, które tworzą nowe kolumny.
- Typowe operacje obejmują połączenie kilku kolumn przy użyciu logiki warunkowej w nową kolumnę złożoną. Na przykład
if var1 > 2 then newvar = 'A' elif var2 = 4 then newvar = 'B'
. Wynikiem tych operacji jest nowa kolumna dla każdego rekordu w moim zbiorze danych. - Na koniec chciałbym dołączyć te nowe kolumny do struktury danych na dysku. Powtórzę krok 2, eksplorując dane za pomocą tabel przestawnych i statystyk opisowych, próbując znaleźć interesujące, intuicyjne relacje do modelowania.
- Typowy plik projektu ma zwykle około 1 GB. Pliki są zorganizowane w taki sposób, że wiersz składa się z zapisu danych konsumenta. Każdy wiersz ma taką samą liczbę kolumn dla każdego rekordu. Tak będzie zawsze.
- Rzadko zdarza się, że przy tworzeniu nowej kolumny dzieliłem wiersze według wierszy. Jednak często zdarza mi się podzbiór wierszy podczas tworzenia raportów lub generowania statystyk opisowych. Na przykład może chciałbym utworzyć prostą częstotliwość dla konkretnej branży, np. Karty kredytowe. Aby to zrobić, wybrałbym tylko te rekordy, w których branża = sprzedaż detaliczna oprócz kolumn, które chcę zgłosić. Jednak podczas tworzenia nowych kolumn wyciągałbym wszystkie wiersze danych i tylko kolumny potrzebne do operacji.
- Proces modelowania wymaga przeanalizowania każdej kolumny, znalezienia interesujących relacji z pewną zmienną wynikową i utworzenia nowych kolumn złożonych opisujących te relacje. Kolumny, które eksploruję, są zwykle wykonywane w małych zestawach. Na przykład skupię się na zestawie powiedzmy 20 kolumn, które dotyczą tylko wartości nieruchomości i obserwuję, jak odnoszą się one do niespłacania pożyczki. Po ich zbadaniu i utworzeniu nowych kolumn przechodzę do innej grupy kolumn, mówię o szkolnictwie wyższym i powtarzam ten proces. To, co robię, to tworzenie zmiennych kandydujących, które wyjaśniają związek między moimi danymi a niektórymi wynikami. Na samym końcu tego procesu stosuję techniki uczenia się, które tworzą równanie z tych kolumn złożonych.
Rzadko dodawałem wiersze do zestawu danych. Prawie zawsze będę tworzyć nowe kolumny (zmienne lub cechy w statystyce / języku uczenia maszynowego).
Odpowiedzi:
Rutynowo używam dziesiątek gigabajtów danych w ten właśnie sposób, np. Mam tabele na dysku, które czytam za pomocą zapytań, tworzę dane i dołączam z powrotem.
Warto przeczytać dokumenty i przeczytać w dalszej części tego wątku, aby uzyskać kilka sugestii dotyczących sposobu przechowywania danych.
Szczegóły, które będą miały wpływ na sposób przechowywania danych, takie jak:
Podaj jak najwięcej szczegółów; i mogę pomóc ci rozwinąć strukturę.
(Podanie przykładu zabawki może umożliwić nam zaoferowanie bardziej szczegółowych zaleceń).
Rozwiązanie
Upewnij się, że masz przynajmniej pandy
0.10.1
zainstalowane.Czytaj pliki iteracyjne fragment po kawałku i wiele zapytań tabelowych .
Ponieważ pytania są zoptymalizowane do pracy w wierszach (o które pytasz), utworzymy tabelę dla każdej grupy pól. W ten sposób łatwo jest wybrać małą grupę pól (która będzie działać z dużym stołem, ale bardziej efektywne jest to zrobić w ten sposób ... Myślę, że mogę w przyszłości naprawić to ograniczenie ... to jest w każdym razie bardziej intuicyjne):
(Poniżej znajduje się pseudokod.)
Odczytywanie plików i tworzenie magazynu (zasadniczo robienie tego, co
append_to_multiple
robi):Teraz masz wszystkie tabele w pliku (w rzeczywistości możesz je przechowywać w osobnych plikach, jeśli chcesz, prawdopodobnie musisz dodać nazwę pliku do mapy_grupy, ale prawdopodobnie nie jest to konieczne).
W ten sposób otrzymujesz kolumny i tworzysz nowe:
Kiedy będziesz gotowy na post_processing:
O kolumnach danych nie ma potrzeby definiowania ŻADNYCH kolumn danych; pozwalają na podselekcję wierszy na podstawie kolumny. Np. Coś takiego:
Mogą być dla Ciebie najbardziej interesujące na końcowym etapie generowania raportu (zasadniczo kolumna danych jest oddzielona od innych kolumn, co może nieco wpłynąć na wydajność, jeśli dużo zdefiniujesz).
Możesz także chcieć:
Daj mi znać, jeśli masz pytania!
źródło
Myślę, że w powyższych odpowiedziach brakuje prostego podejścia, które uważam za bardzo przydatne.
Kiedy mam plik, który jest zbyt duży, aby go załadować do pamięci, dzielę go na wiele mniejszych plików (według wiersza lub kols)
Przykład: w przypadku 30-dniowego handlu danymi o wielkości ~ 30 GB, dzielę je na plik dziennie o wielkości ~ 1 GB. Następnie przetwarzam każdy plik osobno i na końcu agreguję wyniki
Jedną z największych zalet jest to, że umożliwia równoległe przetwarzanie plików (wielu wątków lub procesów)
Inną zaletą jest to, że manipulowanie plikami (np. Dodawanie / usuwanie dat w przykładzie) może być wykonywane za pomocą zwykłych poleceń powłoki, co nie jest możliwe w bardziej zaawansowanych / skomplikowanych formatach plików
To podejście nie obejmuje wszystkich scenariuszy, ale jest bardzo przydatne w wielu z nich
źródło
Teraz, dwa lata po pytaniu, istnieje odpowiednik pand „poza rdzeniem”: dask . To jest świetne! Chociaż nie obsługuje wszystkich funkcji pand, możesz z tym naprawdę zajść daleko.
źródło
dask
.Jeśli twoje zestawy danych mają od 1 do 20 GB, powinieneś dostać stację roboczą z 48 GB pamięci RAM. Następnie Pandy mogą przechowywać cały zestaw danych w pamięci RAM. Wiem, że nie jest to odpowiedź, której tu szukasz, ale wykonywanie obliczeń naukowych na notebooku z 4 GB pamięci RAM nie jest rozsądne.
źródło
Wiem, że to stary wątek, ale myślę, że warto sprawdzić bibliotekę Blaze . Jest zbudowany dla tego rodzaju sytuacji.
Z dokumentów:
Blaze rozszerza użyteczność NumPy i Pandas na przetwarzanie rozproszone i poza rdzeniem. Blaze zapewnia interfejs podobny do interfejsu NumPy ND-Array lub Pandas DataFrame, ale mapuje te znane interfejsy na wiele innych silników obliczeniowych, takich jak Postgres lub Spark.
Edycja: Nawiasem mówiąc, jest obsługiwany przez ContinuumIO i Travisa Oliphanta, autora NumPy.
źródło
Tak jest w przypadku pymongo. Mam również prototypowanie przy użyciu serwera SQL, SQLite, HDF, ORM (SQLAlchemy) w Pythonie. Przede wszystkim pymongo jest bazą danych opartą na dokumencie, więc każda osoba byłaby dokumentem (
dict
atrybutów). Wiele osób tworzy kolekcję i możesz mieć wiele kolekcji (ludzie, giełda, dochód).pd.dateframe -> pymongo Uwaga: Używam
chunksize
in,read_csv
aby zachować od 5 do 10 000 rekordów (pymongo upuszcza gniazdo, jeśli jest większe)zapytanie: gt = większe niż ...
.find()
zwraca iterator, więc zwykle używamichunked
do krojenia na mniejsze iteratory.Co powiesz na sprzężenie, ponieważ zwykle otrzymuję 10 źródeł danych do wklejenia
potem (w moim przypadku czasami muszę
aJoinDF
najpierw zacząć się agresywnie, zanim zostanie „scalony”).Następnie możesz zapisać nowe informacje do swojej głównej kolekcji za pomocą poniższej metody aktualizacji. (gromadzenie logiczne a fizyczne źródła danych).
W przypadku mniejszych wyszukiwań po prostu denormalizuj. Na przykład masz kod w dokumencie i po prostu dodajesz tekst kodu pola i
dict
wyszukujesz podczas tworzenia dokumentów.Teraz masz ładny zestaw danych oparty na osobie, możesz uwolnić swoją logikę w każdej sprawie i zrobić więcej atrybutów. Na koniec możesz wczytać do pandy swoje kluczowe wskaźniki maks. Od 3 do pamięci i przeprowadzić eksplorację osi / ag / danych. Działa to dla 3 milionów rekordów z liczbami / dużym tekstem / kategoriami / kodami / liczbami zmiennoprzecinkowymi / ...
Możesz także użyć dwóch metod wbudowanych w MongoDB (MapReduce i agregacja frameworka). Zobacz tutaj, aby uzyskać więcej informacji na temat struktury agregacji , ponieważ wydaje się ona łatwiejsza niż MapReduce i wydaje się przydatna do szybkiej pracy z agregacją. Zauważ, że nie musiałem definiować swoich pól ani relacji i mogę dodawać elementy do dokumentu. W obecnym stanie szybko zmieniającego się zestawu narzędzi numpy, pand, python MongoDB pomaga mi po prostu zabrać się do pracy :)
źródło
In [96]: test.insert((a[1].to_dict() for a in df.iterrows())) --------------- InvalidDocument: Cannot encode object: 0
. Jakieś pomysły, co może być nie tak? Moja ramka danych składa się ze wszystkich typów int64 i jest bardzo prosta.Zauważyłem to trochę później, ale pracuję z podobnym problemem (modele przedterminowej spłaty kredytu hipotecznego). Moim rozwiązaniem było pominięcie warstwy pandy HDFStore i użycie prostych pytań. Zapisuję każdą kolumnę jako osobną tablicę HDF5 w moim końcowym pliku.
Moim podstawowym obiegiem pracy jest najpierw pobranie pliku CSV z bazy danych. Zgaduję, więc to nie jest tak duże. Następnie przekonwertowałem to na plik HDF5 zorientowany na wiersze, iterując go w pythonie, konwertując każdy wiersz na prawdziwy typ danych i zapisując go do pliku HDF5. Zajmuje to kilkadziesiąt minut, ale nie wykorzystuje pamięci, ponieważ działa tylko wiersz po rzędzie. Następnie „transponuję” zorientowany na wiersze plik HDF5 na zorientowany na kolumny plik HDF5.
Tabela transpozycji wygląda następująco:
Ponowne czytanie to wygląda następująco:
Teraz generalnie uruchamiam to na maszynie z dużą ilością pamięci, więc może nie być wystarczająco ostrożny z użyciem pamięci. Na przykład domyślnie operacja ładowania odczytuje cały zestaw danych.
To na ogół działa dla mnie, ale jest trochę niezgrabne i nie mogę użyć fantazyjnej magii pytable.
Edycja: Prawdziwą zaletą tego podejścia, w porównaniu do domyślnego pytania-tablicy tablic rekordów, jest to, że mogę następnie załadować dane do R przy użyciu h5r, który nie obsługuje tabel. A przynajmniej nie udało mi się załadować heterogenicznych tabel.
źródło
Jedną sztuczką, która okazała się pomocna w przypadkach użycia dużych danych, jest zmniejszenie objętości danych poprzez zmniejszenie precyzji float do 32-bit. Nie ma zastosowania we wszystkich przypadkach, ale w wielu aplikacjach 64-bitowa precyzja to przesada, a 2x oszczędność pamięci jest tego warta. Aby uczynić oczywisty punkt jeszcze bardziej oczywistym:
źródło
Jak zauważyli inni, po kilku latach pojawił się ekwiwalent pand „poza rdzeniem”: dask . Chociaż dask nie zastępuje pand, a cała jego funkcjonalność wyróżnia się z kilku powodów:
Dask to elastyczna biblioteka obliczeń równoległych do obliczeń analitycznych, zoptymalizowana pod kątem dynamicznego planowania zadań dla interaktywnych obciążeń obliczeniowych zbiorów „Big Data”, takich jak tablice równoległe, ramki danych i listy, które rozszerzają popularne interfejsy, takie jak NumPy, Pandas lub iteratory Python, na większe- środowiska niż pamięciowe lub rozproszone i skalowane od laptopów do klastrów.
i dodać prosty przykładowy kod:
zastępuje niektóre kody pand takie jak to:
i, co szczególnie godne uwagi, zapewnia za pośrednictwem
concurrent.futures
interfejsu ogólną infrastrukturę do przesyłania niestandardowych zadań:źródło
Warto również wspomnieć o tym Ray ,
jest to rozproszona platforma obliczeniowa, która ma własną implementację dla pand w sposób rozproszony.
Po prostu zastąp import pand, a kod powinien działać tak, jak jest:
więcej szczegółów tutaj:
https://rise.cs.berkeley.edu/blog/pandas-on-ray/
źródło
Jeszcze jedna odmiana
Wiele operacji wykonywanych w pandach można również wykonać jako zapytanie db (sql, mongo)
Korzystanie z RDBMS lub mongodb pozwala na wykonanie niektórych agregacji w zapytaniu DB (które jest zoptymalizowane dla dużych danych i efektywnie wykorzystuje pamięć podręczną i indeksy)
Później możesz wykonać przetwarzanie końcowe za pomocą pand.
Zaletą tej metody jest to, że zyskujesz optymalizacje DB do pracy z dużymi danymi, a jednocześnie definiujesz logikę w deklaratywnej składni wysokiego poziomu - i nie musisz zajmować się szczegółami decydowania, co robić w pamięci, a co robić rdzeniowy.
I chociaż język zapytań i pandy są różne, zwykle nie jest skomplikowane tłumaczenie części logiki z jednej na drugą.
źródło
Rozważ Ruffus, jeśli pójdziesz prostą ścieżką tworzenia potoku danych, który jest podzielony na wiele mniejszych plików.
źródło
Ostatnio natknąłem się na podobny problem. Znalazłem po prostu czytanie danych w kawałkach i dołączanie ich, gdy piszę je w kawałkach do tego samego pliku csv, działa dobrze. Moim problemem było dodanie kolumny daty na podstawie informacji w innej tabeli, przy użyciu wartości niektórych kolumn w następujący sposób. Może to pomóc osobom zdezorientowanym przez dask i hdf5, ale lepiej znającym pandy takie jak ja.
źródło
Chciałbym zwrócić uwagę na pakiet Vaex.
Zajrzyj do dokumentacji: https://vaex.readthedocs.io/en/latest/ Interfejs API jest bardzo zbliżony do interfejsu API pand.
źródło
Dlaczego Pandy? Próbowałeś już Standard Python ?
Zastosowanie standardowego pytona bibliotecznego. Pandy podlegają częstym aktualizacjom, nawet w najnowszej wersji stabilnej wersji.
Za pomocą standardowej biblioteki python Twój kod będzie zawsze działał.
Jednym ze sposobów na zrobienie tego jest wyobrażenie sobie, w jaki sposób chcesz, aby twoje dane były przechowywane, i jakie pytania chcesz rozwiązać w odniesieniu do danych. Następnie narysuj schemat, w jaki sposób możesz uporządkować swoje dane (tabele myślowe), które pomogą ci zapytać o dane, niekoniecznie normalizację.
Możesz dobrze wykorzystać:
Z czasem RAM i HDD stają się coraz tańsze, a standardowy python 3 jest powszechnie dostępny i stabilny.
źródło
W tej chwili pracuję „jak” ty, tylko na niższą skalę, dlatego nie mam PoC dla mojej sugestii.
Wydaje mi się jednak, że odnajduję sukces w używaniu marynaty jako systemu buforowania i outsourcingu wykonywania różnych funkcji do plików - wykonywanie tych plików z mojego pliku komandosów / głównego; Na przykład używam pliku przygotuj_użytkownika.py do konwersji typów obiektów, podzielenia zestawu danych na testowy, sprawdzania poprawności i prognozowania.
Jak działa buforowanie marynowane? Używam ciągów w celu uzyskania dostępu do plików dynamicznych, które są tworzone dynamicznie, w zależności od tego, które parametry i zestawy danych zostały przekazane (dzięki temu próbuję przechwycić i ustalić, czy program był już uruchomiony, używając .shape dla zestawu danych, dykta dla przekazanego parametry). Przestrzegając tych środków, otrzymuję ciąg, aby spróbować znaleźć i odczytać plik .pickle i mogę, jeśli zostanie znaleziony, pominąć czas przetwarzania, aby przejść do wykonania, nad którym teraz pracuję.
Korzystając z baz danych, napotkałem podobne problemy i dlatego czerpałem radość z korzystania z tego rozwiązania, jednak - na pewno istnieje wiele ograniczeń - na przykład przechowywanie ogromnych zestawów pikli z powodu redundancji. Aktualizowanie tabeli przed i po transformacji można wykonać przy użyciu odpowiedniego indeksowania - sprawdzanie poprawności informacji otwiera całą inną książkę (próbowałem skonsolidować przeszukane dane czynszu i po 2 godzinach przestałem korzystać z bazy danych - ponieważ chciałbym po niej wrócić każdy proces transformacji)
Mam nadzieję, że moje 2 centy ci w jakiś sposób pomogą.
Pozdrowienia.
źródło