Jak iterować po wierszach DataFrame w Pandach?
Odpowiedź: NIE * !
Iteracja w pandach jest anty-wzorem i jest czymś, co powinieneś zrobić tylko wtedy, gdy wyczerpiesz każdą inną opcję. Nie powinieneś używać żadnej funkcji z „ iter
” w jej nazwie dla więcej niż kilku tysięcy wierszy, w przeciwnym razie będziesz musiał przyzwyczaić się do długiego oczekiwania.
Czy chcesz wydrukować ramkę danych? Zastosowanie DataFrame.to_string()
.
Chcesz coś obliczyć? W takim przypadku wyszukaj metody w tej kolejności (lista zmodyfikowana tutaj ):
- Wektoryzacja
- Procedury cytonowe
- Zrozumienie listy (
for
pętla waniliowa )
DataFrame.apply()
: i) Redukcje, które można wykonać w cytonie, ii) Iteracja w przestrzeni pytona
DataFrame.itertuples()
i iteritems()
DataFrame.iterrows()
iterrows
i itertuples
(oba otrzymujące wiele głosów w odpowiedziach na to pytanie) powinny być używane w bardzo rzadkich okolicznościach, takich jak generowanie obiektów wierszy / imion do przetwarzania sekwencyjnego, co jest naprawdę jedyną rzeczą, do której te funkcje są przydatne.
Apel do organu
Na stronie z dokumentami na iteracji znajduje się ogromne czerwone pole ostrzegawcze z napisem:
Iteracja po obiektach pand jest zwykle powolna. W wielu przypadkach ręczne iterowanie po wierszach nie jest potrzebne [...].
* To jest trochę bardziej skomplikowane niż „nie”. df.iterrows()
jest poprawną odpowiedzią na to pytanie, ale „wektoryzacja operacji” jest lepsza. Przyznaję, że istnieją okoliczności, w których nie można uniknąć iteracji (na przykład niektóre operacje, w których wynik zależy od wartości obliczonej dla poprzedniego wiersza). Jednak potrzeba pewnej znajomości biblioteki, aby wiedzieć, kiedy. Jeśli nie masz pewności, czy potrzebujesz rozwiązania iteracyjnego, prawdopodobnie nie. PS: Aby dowiedzieć się więcej o moim uzasadnieniu napisania tej odpowiedzi, przejdź na sam dół.
Wiele podstawowych operacji i obliczeń jest „wektoryzowanych” przez pandy (za pomocą NumPy lub funkcji cytonizowanych). Obejmuje to operacje arytmetyczne, porównania, (większość) redukcji, przekształcanie (takie jak przestawianie), łączenia i operacje grupowania. Przejrzyj dokumentację Essential Basic Functionality, aby znaleźć odpowiednią metodę wektorową dla twojego problemu.
Jeśli nie istnieje, możesz napisać własny przy użyciu niestandardowych rozszerzeń cytonów .
Wyjaśnienia list powinny być Twoim następnym portem wywoławczym, jeśli 1) nie ma dostępnego rozwiązania wektorowego, 2) wydajność jest ważna, ale niewystarczająco ważna, aby przejść przez kłopot związany z cytonizacją kodu, i 3) próbujesz przeprowadzić transformację elementarną na twoim kodzie. Istnieje wiele dowodów na to, że zrozumienie listy jest wystarczająco szybkie (a czasem nawet szybsze) do wielu typowych zadań pand.
Formuła jest prosta,
# iterating over one column - `f` is some function that processes your data
result = [f(x) for x in df['col']]
# iterating over two columns, use `zip`
result = [f(x, y) for x, y in zip(df['col1'], df['col2'])]
# iterating over multiple columns - same data type
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].to_numpy()]
# iterating over multiple columns - differing data type
result = [f(row[0], ..., row[n]) for row in zip(df['col1'], ..., df['coln'])]
Jeśli umiesz zawrzeć logikę biznesową w funkcji, możesz skorzystać ze spisu, który ją wywołuje. Możesz sprawić, by dowolnie złożone rzeczy działały dzięki prostocie i szybkości surowego pytona.
Wyjaśnienia dotyczące
listy zastrzeżeń zakładają, że dane są łatwe w obsłudze - oznacza to, że typy danych są spójne i nie masz NaN, ale nie zawsze można to zagwarantować.
- Pierwsza jest bardziej oczywista, ale w przypadku NaN preferuj wbudowane metody pand, jeśli istnieją (ponieważ mają znacznie lepszą logikę obsługi przypadków narożnych) lub upewnij się, że logika biznesowa zawiera odpowiednią logikę obsługi NaN.
- W przypadku mieszanych typów danych należy iterować
zip(df['A'], df['B'], ...)
zamiast, df[['A', 'B']].to_numpy()
ponieważ ten drugi domyślnie upcastuje dane do najbardziej powszechnego typu. Na przykład, jeśli A jest liczbą, a B jest ciągiem, to_numpy()
rzutuje całą tablicę na ciąg, co może nie być tym, czego chcesz. Na szczęście zip
pingowanie kolumn razem jest najprostszym obejściem tego problemu.
* YMMV z powodów przedstawionych w zastrzeżeń sekcji powyżej.
Oczywisty przykład
Pokażmy różnicę na prostym przykładzie dodania dwóch kolumn pand A + B
. Jest to operatyzowalna wektoryzacja, więc łatwo będzie skontrolować wydajność metod omówionych powyżej.
Kod porównawczy, w celach informacyjnych.
Powinienem jednak wspomnieć, że nie zawsze jest to tak cięte i suche. Czasami odpowiedź na „najlepszą metodę operacji” brzmi „zależy to od twoich danych”. Radzę przetestować różne podejścia do swoich danych, zanim zdecydujesz się na jedno.
Dalsza lektura
* Metody łańcuchowe pand są „wektoryzowane” w tym sensie, że są określone w serii, ale działają na każdym elemencie. Mechanizmy leżące u ich podstaw są wciąż iteracyjne, ponieważ operacje łańcuchowe są z natury trudne do wektoryzacji.
Dlaczego napisałem tę odpowiedź
Częstym trendem, który zauważam od nowych użytkowników, jest zadawanie pytań w formie „w jaki sposób mogę iterować nad moim df, aby zrobić X?”. Pokazuje kod, który wywołuje iterrows()
podczas wykonywania czegoś w pętli for. Oto dlaczego. Nowy użytkownik biblioteki, który nie został zaznajomiony z koncepcją wektoryzacji, prawdopodobnie wyobrazi sobie kod, który rozwiązuje ich problem podczas iteracji danych, aby coś zrobić. Nie wiedząc, jak wykonać iterację w DataFrame, pierwszą rzeczą, którą robią, jest Google i kończy się tutaj, na to pytanie. Następnie widzą zaakceptowaną odpowiedź, mówiąc im, jak to zrobić, i zamykają oczy i uruchamiają ten kod, nie pytając nigdy, czy iteracja nie jest właściwa.
Ta odpowiedź ma na celu pomóc nowym użytkownikom zrozumieć, że iteracja niekoniecznie jest rozwiązaniem każdego problemu oraz że mogą istnieć lepsze, szybsze i bardziej idiomatyczne rozwiązania oraz że warto poświęcić czas na ich zbadanie. Nie próbuję rozpocząć wojny iteracji z wektoryzacją, ale chcę, aby nowi użytkownicy byli informowani podczas opracowywania rozwiązań ich problemów z tą biblioteką.