Mam DataFrame
z pand:
import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df
Wynik:
c1 c2
0 10 100
1 11 110
2 12 120
Teraz chcę iterować po wierszach tej ramki. Dla każdego wiersza chcę mieć dostęp do jego elementów (wartości w komórkach) według nazw kolumn. Na przykład:
for row in df.rows:
print row['c1'], row['c2']
Czy można to zrobić w pandach?
Znalazłem podobne pytanie . Ale nie daje mi odpowiedzi, której potrzebuję. Na przykład zaleca się użycie:
for date, row in df.T.iteritems():
lub
for row in df.iterrows():
Ale nie rozumiem, czym row
jest przedmiot i jak mogę z nim pracować.
iter*
funkcje powinny być używane w bardzo rzadkich okolicznościach. Również powiązane .iterrows
, istnieją lepsze sposoby na iterację w DataFrame, możesz równie dobrze po prostu iterować listę list w tym momencie. Jeśli jesteś w punkcie, w którym nie robisz nic poza iteracją DataFrame, tak naprawdę nie ma żadnej korzyści z używania DataFrame (zakładając, że iteracja nad nim jest jedyną rzeczą, którą z tym robisz). Tylko mój 2c.pandas
to wybór odczytu pliku csv, nawet jeśli zestaw danych jest mały. Po prostu łatwiej jest programować manipulowanie danymi za pomocą interfejsów APIOdpowiedzi:
DataFrame.iterrows to generator generujący zarówno indeks, jak i wiersz
źródło
431341610650
read read as4.31E+11
. Czy istnieje sposób na zachowanie dtypów?itertuples
, jak wyjaśniono poniżej. Zobacz także pandas.pydata.org/pandas-docs/stable/generated/…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 ):
for
pętla waniliowa )DataFrame.apply()
: i) Redukcje, które można wykonać w cytonie, ii) Iteracja w przestrzeni pytonaDataFrame.itertuples()
iiteritems()
DataFrame.iterrows()
iterrows
iitertuples
(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:
* 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ół.Szybszy niż zapętlenie : wektoryzacja , cython
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 .
Następna najlepsza rzecz: lista zrozumień *
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,
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ć.
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ęściezip
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
10 minut do pand i niezbędna podstawowa funkcjonalność - Przydatne linki, które przedstawiają pandy i bibliotekę wektorowych * / cytonizowanych funkcji.
Zwiększanie wydajności - elementarz z dokumentacji na temat ulepszania standardowych operacji pand
Czy pętle for w pandach są naprawdę złe? Kiedy powinno mnie to obchodzić? - szczegółowy opis przeze mnie opisów list i ich przydatności do różnych operacji (głównie tych obejmujących dane nienumeryczne)
Kiedy powinienem kiedykolwiek chcieć użyć pandas apply () w moim kodzie? -
apply
jest wolny (ale nie tak wolny jakiter*
rodzina. Są jednak sytuacje, w których można (lub należy) rozważyćapply
poważną alternatywę, szczególnie w niektórychGroupBy
operacjach).* 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ą.
źródło
zip(df['A'], df['B'])
zamiastdf.iterrows()
.iterrows()
iteracji, jeśli i kiedy istnieją lepsze alternatywy.for
same pętle są w porządku, ale zrozumienie listy jest lepsze, jeśli wykonujesz iteracyjnie transformacje elementarne.DataFrame.values
przekonwertuje każdą kolumnę na wspólny typ danych.DataFrame.to_numpy()
robi to też. Na szczęście możemy używaćzip
dowolnej liczby kolumn.Najpierw zastanów się, czy naprawdę musisz iterować wiersze w ramce danych. Zobacz tę odpowiedź, aby znaleźć alternatywy.
Jeśli nadal musisz wykonywać iterację po wierszach, możesz użyć poniższych metod. Zwróć uwagę na kilka ważnych zastrzeżeń, które nie zostały wymienione w żadnej z pozostałych odpowiedzi.
DataFrame.iterrows ()
DataFrame.itertuples ()
itertuples()
ma być szybszy niżiterrows()
Ale uważaj, zgodnie z dokumentami (w tej chwili pandy 0.24.2):
iterrows:
dtype
może nie pasować między wierszamiiterrows: Nie modyfikuj wierszy
Zamiast tego użyj DataFrame.apply () :
itertule:
Zobacz dokumentację pandy na temat iteracji, aby uzyskać więcej informacji.
źródło
for row in df[['c1','c2']].itertuples(index=True, name=None):
aby uwzględnić tylko niektóre kolumny w iteratorze wierszy.getattr(row, "c1")
możesz użyć justrow.c1
.getattr(row, "c1")
zamiast tegorow.c1
, stracisz jakąkolwiek przewagę wydajnościitertuples
, a jeśli faktycznie potrzebujesz dostać się do nieruchomości za pośrednictwem ciągu, powinieneś użyć iterrows.numba
icython
(te same dokumenty mówią, że „zawsze najpierw warto zoptymalizować w Pythonie”). Napisałem tę odpowiedź, aby pomóc innym uniknąć (czasem frustrujących) problemów, ponieważ żadna z pozostałych odpowiedzi nie wspomina o tych zastrzeżeniach. Wprowadzanie nikogo w błąd lub mówienie „tak należy robić” nigdy nie było moim zamiarem. Poprawiłem odpowiedź.Powinieneś użyć
df.iterrows()
. Chociaż iteracja rząd po rzędzie nie jest szczególnie wydajna, ponieważSeries
obiekty muszą być tworzone.źródło
Chociaż
iterrows()
jest to dobra opcja, czasamiitertuples()
może być znacznie szybsza:źródło
for a,b,c in izip(df["a"],df["b"],df["c"]:
prawie równie szybko.iterrows()
każdy wiersz danych w serii,itertuples()
ale nie.df
jest tworzona ze słownika, więcrow[1]
może odnosić się do dowolnej kolumny. Jak się okazuje, czasy są mniej więcej takie same dla liczb całkowitych i liczb zmiennoprzecinkowych.Możesz także użyć
df.apply()
do iteracji po wierszach i uzyskać dostęp do wielu kolumn dla funkcji.docs: DataFrame.apply ()
źródło
apply
nie „iteruje się” nad wierszami, a raczej stosuje funkcję wierszowo. Powyższy kod nie będzie działać, jeśli naprawdę zrobić iteracji potrzeba i indeksami, na przykład przy porównywaniu wartości w różnych wierszach (w tym przypadku można zrobić nic poza iteracji).Możesz użyć funkcji df.iloc w następujący sposób:
źródło
itertuples
zachowuje typy danych, ale pozbywa się nazw, których nie lubi.iterrows
robi coś przeciwnego.for i in range(df.shape[0])
może nieco przyspieszyć to podejście, wciąż jest około 3,5 razy wolniejsze niż powyższe podejście iterrows () w mojej aplikacji.my_iter = df.itertuples()
potrzeba podwójnej pamięci i dużo czasu na jej skopiowanie. to samo dlaiterrows()
.Szukałem sposobu iteracji w wierszach ORAZ kolumnach i zakończyłem tutaj tak:
źródło
Możesz napisać własny iterator, który implementuje
namedtuple
Jest to bezpośrednio porównywalne z
pd.DataFrame.itertuples
. Chcę wykonać to samo zadanie z większą wydajnością.Dla podanej ramki danych z moją funkcją:
Lub z
pd.DataFrame.itertuples
:Kompleksowy test
Testujemy udostępnianie wszystkich kolumn i ich podział.
źródło
intertuples
pomarańczowa linia to lista iteratorów przez blok wydajności.interrows
nie jest porównywany.Jak skutecznie iterować?
Jeśli naprawdę musisz iterować ramkę danych pand, prawdopodobnie będziesz chciał uniknąć używania iterrows () . Istnieją różne metody i zwykle
iterrows()
daleki jest od bycia najlepszym. itertuples () może być 100 razy szybszy.W skrócie:
df.itertuples(name=None)
. W szczególności, gdy masz stałą liczbę kolumn i mniej niż 255 kolumn. Patrz punkt (3)df.itertuples()
chyba że kolumny zawierają znaki specjalne, takie jak spacje lub „-”. Punkt 2itertuples()
nawet jeśli twoja ramka danych ma dziwne kolumny, używając ostatniego przykładu. Patrz punkt (4)iterrows()
wtedy, gdy nie możesz poprzednich rozwiązań. Zobacz punkt (1)Różne metody iteracji po wierszach w ramce danych pandy:
Wygeneruj losową ramkę danych z milionem wierszy i 4 kolumnami:
1) Zwykle
iterrows()
jest wygodne, ale cholernie wolne:2) Wartość domyślna
itertuples()
jest już znacznie szybsza, ale nie działa z nazwami kolumn, takimi jakMy Col-Name is very Strange
(należy unikać tej metody, jeśli kolumny są powtarzane lub jeśli nazwy kolumny nie można po prostu przekonwertować na nazwę zmiennej python):3) Domyślne
itertuples()
użycie name = None jest jeszcze szybsze, ale nie bardzo wygodne, ponieważ musisz zdefiniować zmienną dla kolumny.4) Wreszcie, nazwany
itertuples()
jest wolniejszy niż poprzedni punkt, ale nie musisz definiować zmiennej dla kolumny i działa z nazwami kolumn, takimi jakMy Col-Name is very Strange
.Wynik:
Ten artykuł jest bardzo interesującym porównaniem iteracji i itertu
źródło
Aby zapętlić wszystkie wiersze
dataframe
, możesz użyć:źródło
źródło
Czasami przydatnym wzorem jest:
Co skutkuje w:
źródło
Aby zapętlić wszystkie wiersze
dataframe
ai wygodnie użyć wartości każdego wiersza , można przekonwertować je na s. Na przykład:namedtuples
ndarray
Iterowanie po wierszach:
prowadzi do:
Należy pamiętać, że jeśli
index=True
, indeks jest dodany jako pierwszy element krotki , co może być niekorzystne dla niektórych aplikacji.źródło
Istnieje sposób na iterację rzutów wierszy podczas uzyskiwania w zamian DataFrame, a nie serii. Nie widzę nikogo wspominającego, że można przekazać indeks jako listę dla wiersza, który ma zostać zwrócony jako DataFrame:
Zwróć uwagę na użycie podwójnych nawiasów. Zwraca DataFrame z pojedynczym wierszem.
źródło
Użyłbym zarówno do przeglądania, jak i modyfikowania wartości
iterrows()
. W pętli for i przy użyciu rozpakowywania krotek (patrz przykładi, row
:) używamrow
tylko do przeglądania wartości i używami
zloc
metodą, gdy chcę zmodyfikować wartości. Jak stwierdzono w poprzednich odpowiedziach, tutaj nie powinieneś modyfikować czegoś, nad czym się iterujesz.Tutaj
row
pętla jest kopią tego wiersza, a nie jego widokiem. Dlatego NIE powinieneś pisać czegoś takiegorow['A'] = 'New_Value'
, nie spowoduje to modyfikacji DataFrame. Możesz jednak użyći
iloc
określić DataFrame do wykonania pracy.źródło
Wiem, że spóźniłem się na przyjęcie, ale chciałem tylko dodać powyższą odpowiedź @ cs95, która moim zdaniem powinna być odpowiedzią przyjętą. W swojej odpowiedzi pokazuje, że wektoryzacja pand znacznie przewyższa inne metody obliczania pand przy użyciu ramek danych.
Chciałem dodać, że jeśli najpierw przekonwertujesz ramkę danych na tablicę numpy, a następnie użyjesz wektoryzacji, będzie to nawet szybsze niż wektoryzacja ramki danych pandy (i obejmuje to czas, aby ponownie przekształcić ją w serię ramek danych).
Jeśli dodasz następujące funkcje do kodu testu porównawczego @ cs95, stanie się to dość oczywiste:
źródło
Możesz także wykonać
numpy
indeksowanie, aby uzyskać jeszcze większe przyspieszenia. To nie jest tak naprawdę iteracja, ale działa znacznie lepiej niż iteracja dla niektórych aplikacji.Możesz także rzucić go na tablicę. Te indeksy / selekcje powinny już działać jak tablice Numpy, ale napotkałem problemy i musiałem przesyłać
źródło
Jest tak wiele sposobów na iterację wierszy w ramce danych pand. Jednym z bardzo prostych i intuicyjnych sposobów jest:
źródło
W tym przykładzie użyto programu iloc do wyodrębnienia każdej cyfry w ramce danych.
źródło
Niektóre biblioteki (np. Używana przeze mnie biblioteka międzyoperacyjna Java) wymagają przekazywania wartości w jednym rzędzie, na przykład w przypadku przesyłania strumieniowego danych. Aby odtworzyć naturę przesyłania strumieniowego, „przesyłam strumieniowo” moje wartości ramek danych jedna po drugiej, napisałem poniżej, co jest przydatne od czasu do czasu.
Które mogą być użyte:
I zachowuje mapowanie wartości / nazw dla iterowanych wierszy. Oczywiście jest o wiele wolniejszy niż stosowanie aplikacji i Cython, jak wskazano powyżej, ale w niektórych okolicznościach jest konieczne.
źródło
W skrócie
Szczegóły w tym filmie
Reper
źródło