Pandalar'da bir DataFrame'deki satırlar üzerinde nasıl yineleme yapılır?


1948

Bir var DataFramepandalar gelen:

import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df

Çıktı:

   c1   c2
0  10  100
1  11  110
2  12  120

Şimdi bu çerçevenin satırları üzerinde yineleme yapmak istiyorum. Her satır için öğelerine (hücrelerdeki değerler) sütunların adıyla erişebilmek istiyorum. Örneğin:

for row in df.rows:
   print row['c1'], row['c2']

Bunu pandalarda yapmak mümkün mü?

Benzer soruyu buldum . Ama bana ihtiyacım olan cevabı vermiyor. Örneğin, orada kullanılması önerilir:

for date, row in df.T.iteritems():

veya

for row in df.iterrows():

Ama rownesnenin ne olduğunu ve onunla nasıl çalışabileceğimi anlamıyorum.


11
Df.iteritems (), satırlar yerine sütunlar üzerinde yinelenir. Böylece, satırlar üzerinde yineleme yapmak için, ("T"), satırları ve sütunları birbirine (çapraz üzerinde yansıtmak) değiştirmek anlamına gelir. Sonuç olarak, df.T.iteritems ()
Stefan Gruenwald

11
Bu konuya yeniyseniz ve pandalara yeni başlayan biriyseniz, DEĞİL DEĞİLDİR! Veri çerçeveleri üzerinde yineleme bir anti-desen ve çok fazla beklemeye alışmak istemiyorsanız yapmamanız gereken bir şey. Ne yapmaya çalıştığınıza bağlı olarak , muhtemelen daha iyi alternatifler vardır . iter*Fonksiyonlar çok nadir durumlarda kullanılmalıdır. Ayrıca ilgili .
cs95

18
CS95'in söylediklerinin aksine, bir veri çerçevesi üzerinde yineleme yapmak için mükemmel nedenler vardır, bu nedenle yeni kullanıcılar cesaretini kırmamalıdır. Bir örnek, her satırın değerlerini girdi olarak kullanarak bir kod yürütmek istiyorsanız. Ayrıca, veri çerçeveniz makul derecede küçükse (örneğin 1000 öğeden az), performans gerçekten bir sorun değildir.
oulenz

1
@oulenz: Herhangi bir nedenden dolayı API'yı tasarlandığı amaç için (yüksek performanslı veri dönüşümleri) kullanma karşısında uçmak istiyorsanız, o zaman misafirim olun. Ama en azından, kullanmayın iterrows, bir DataFrame üzerinde yineleme yapmanın daha iyi yolları vardır, o noktada listelerin listesini tekrarlayabilirsiniz. DataFrames üzerinden yineleme yapmaktan başka bir şey yapma noktasındaysanız, bir DataFrame kullanmanın gerçekten bir faydası yoktur (yinelemenin onunla yaptığınız tek şey olduğunu varsayarsak). Sadece benim 2c.
cs95

7
İkinci olarak @oulenz. Bildiğim kadarıyla pandasveri kümesi küçük olsa bile bir csv dosyasını okuma seçimdir. Verileri API'lar ile değiştirmek için programlamak daha kolay
Chris

Yanıtlar:


2632

DataFrame.iterrows hem dizin hem de satır sağlayan bir jeneratördür

import pandas as pd
import numpy as np

df = pd.DataFrame([{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}])

for index, row in df.iterrows():
    print(row['c1'], row['c2'])

Output: 
   10 100
   11 110
   12 120

207
Not: "iterrows her satır için Serisi döndürür olduğundan, gelmez satırlar arasında dtypes korumak." Ayrıca, " Tekrarladığınız bir şeyi asla değiştirmemelisiniz ." Pandalara
viddik13

3
@ viddik13 bu harika bir not teşekkürler. Bu nedenle, 431341610650nerede okunduğu gibi sayısal değerlerin olduğu bir durumla karşılaştım 4.31E+11. Türleri korumanın bir yolu var mı?
Aziz Alto

26
@AzizAlto itertuples, aşağıda açıklandığı gibi kullanın . Ayrıca bkz pandas.pydata.org/pandas-docs/stable/generated/…
Axel

101
Kaşıntıları kullanmayın. Itertuples daha hızlıdır ve veri türünü korur. Daha fazla bilgi
James L.

11
Gönderen belgeler : "yineleme pandalar nesneler aracılığıyla yavaş genellikle çok durumda, satırlar üzerinde elle yineleme [...] gerekli değildir.". Cevabınız doğru (soru bağlamında) ama hiçbir yerde bundan bahsetmiyor, bu yüzden çok iyi değil.
cs95

458

Pandalar'da bir DataFrame'deki satırlar üzerinde nasıl yineleme yapılır?

Cevap: YAPMAYIN * !

Pandalarda yineleme bir anti-kalıptır ve yalnızca diğer tüm seçenekleri tükettiğinizde yapmanız gereken bir şeydir. " iter" İle herhangi bir işlevi birkaç bin satırdan fazla kullanmamalısınız veya çok fazla beklemeye alışmanız gerekir.

Bir DataFrame yazdırmak istiyor musunuz? Kullanın DataFrame.to_string().

Bir şey hesaplamak ister misiniz? Bu durumda, bu sırayla yöntemleri arayın (liste buradan değiştirilir ):

  1. Vektoriyal
  2. Cython rutinleri
  3. Liste Anlamaları (vanilya fordöngüsü)
  4. DataFrame.apply(): i) Cython'da yapılabilecek azaltmalar, ii) Python uzayında yineleme
  5. DataFrame.itertuples() ve iteritems()
  6. DataFrame.iterrows()

iterrowsve itertuples(her ikisi de bu soruya verilen cevaplarda çok oy alan) sıralı işlem için satır nesneleri / adetuples oluşturma gibi çok nadir durumlarda kullanılmalıdır.

Otoriteye İtiraz
İfadedeki dokümanlar sayfasında büyük bir kırmızı uyarı kutusu vardır:

Panda nesneleri üzerinden yineleme genellikle yavaştır. Çoğu durumda, satırlar üzerinde manuel olarak yineleme yapılması gerekmez [...].

* Aslında "yapma" dan biraz daha karmaşıktır. df.iterrows()bu sorunun doğru cevabıdır, ancak "op'larınızı vektörleştirin" daha iyidir. Yinelemenin önlenemeyeceği durumlar olduğunu kabul edeceğim (örneğin, sonucun bir önceki satır için hesaplanan değere bağlı olduğu bazı işlemler). Ancak, kütüphanenin ne zaman olduğunu bilmek biraz aşina olur. Yinelemeli bir çözüme ihtiyacınız olup olmadığından emin değilseniz, muhtemelen ihtiyacınız yoktur. Not: Bu cevabı yazmamın mantığı hakkında daha fazla bilgi edinmek için en aşağıya atlayın.


Döngüden Daha Hızlı: Vektörleşme , Cython

Çok sayıda temel işlem ve hesaplama pandalar tarafından "vektörleştirilir" (NumPy veya Cythonized fonksiyonlar aracılığıyla). Bu aritmetik, karşılaştırmalar, (çoğu) indirgeme, yeniden şekillendirme (döndürme gibi), birleştirme ve gruplama işlemlerini içerir. Sorununuz için uygun bir vektörize edilmiş yöntem bulmak için Essential Basic Functionality ile ilgili belgelere bakın .

Hiçbiri yoksa, özel cython uzantılarını kullanarak kendiniz yazmaktan çekinmeyin .


Sonraki En İyi Şey: Liste Anlamaları *

1) vektörleştirilmiş bir çözüm yoksa, 2) performans önemlidir, ancak kodunuzu şifrelemekle uğraşmak için yeterince önemli değilse ve 3) elemanlı dönüşüm gerçekleştirmeye çalışıyorsanız, liste anlaşmaları bir sonraki çağrı limanınız olmalıdır. kodunuzda. Liste kavrayışlarının birçok yaygın panda görevi için yeterince hızlı (hatta bazen daha hızlı) olduğunu gösteren iyi bir kanıt vardır.

Formül basit,

# 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'])]

İş mantığınızı bir işleve kapsülleyebiliyorsanız, onu çağıran bir liste kavrama kullanabilirsiniz. Ham python'un basitliği ve hızı ile keyfi olarak karmaşık şeylerin çalışmasını sağlayabilirsiniz.

Uyarılar
Listesi kavrayışları, verilerinizin üzerinde çalışmanın kolay olduğunu varsayar - bunun anlamı, veri türlerinizin tutarlı olması ve NaN'lerinizin olmamasıdır, ancak bu her zaman garanti edilemez.

  1. Birincisi daha açıktır, ancak NaN'lerle uğraşırken, varsa yerleşik panda yöntemlerini tercih edin (çünkü çok daha iyi köşe-vaka işleme mantığı vardır) veya iş mantığınızın uygun NaN işleme mantığını içerdiğinden emin olun.
  2. Karışık veri türleri ile uğraşırken zaman içinde yineleme gereken zip(df['A'], df['B'], ...)yerine df[['A', 'B']].to_numpy()ikincisi olarak örtük en yaygın türüne verileri upcasts. Örnek olarak A, sayısal ve B dize ise, to_numpy()dizinin tamamını dizeye yayınlar; bu, istediğiniz gibi olmayabilir. Neyse ki zipsütunlarınızı birbirine pingleyin, bunun en basit çözümü budur.

* Yukarıdaki Uyarılar bölümünde belirtilen nedenlerden dolayı YMMV .


Açık Bir Örnek

İki panda sütunu eklemenin basit bir örneğiyle farkı gösterelim A + B. Bu vektörleştirilebilir bir operatöre sahiptir, bu nedenle yukarıda tartışılan yöntemlerin performansını karşılaştırmak kolay olacaktır.

resim açıklamasını buraya girin

Referans için karşılaştırma kodu.

Bununla birlikte, her zaman bu kesik ve kuru olmadığını belirtmeliyim. Bazen "bir operasyon için en iyi yöntem nedir" cevabı "verilerinize bağlıdır". Tavsiyem, bunlara karar vermeden önce verilerinizdeki farklı yaklaşımları test etmektir.


Daha fazla okuma

* Pandalar dizesi yöntemleri, seride belirtilmiş olmaları, ancak her bir öğe üzerinde çalışması anlamında "vektörleştirilmiştir". Altta yatan mekanizmalar hala yinelemelidir, çünkü dize işlemlerini doğal olarak vektörleştirmek zordur.


Bu Cevabı Neden Yazdım

Yeni kullanıcılardan fark ettiğim yaygın bir eğilim, "X yapmak için df'm üzerinden nasıl yineleyebilirim?" Şeklinde sorular sormaktır. iterrows()For döngüsü içinde bir şey yaparken çağıran kod gösteriliyor . İşte nedeni. Kütüphaneye, vektörleştirme kavramıyla tanışmamış yeni bir kullanıcı, muhtemelen bir şey yapmak için verilerini yineleyen sorununu çözen kodu öngörecektir. Bir DataFrame üzerinde nasıl yineleneceğini bilmeden, yaptıkları ilk şey bu soruda Google bunu ve burada sona eriyor. Daha sonra kendilerine nasıl yapılacağını söyleyen kabul edilen cevabı görürler ve yinelemenin yapılması gereken doğru bir şey olup olmadığını hiç sorgulamadan gözlerini kapatır ve bu kodu çalıştırırlar.

Bu cevabın amacı, yeni kullanıcıların yinelemenin her sorunun çözümü olması gerekmediğini ve daha iyi, daha hızlı ve daha deyimsel çözümlerin var olabileceğini ve bunları keşfetmeye zaman ayırmaya değer olduğunu anlamalarına yardımcı olmaktır. Vectorization vs yineleme savaşı başlatmaya çalışmıyorum, ancak yeni kullanıcıların bu kütüphane ile ilgili sorunlarına çözüm geliştirirken bilgilendirilmesini istiyorum.


24
Bu, pandalarla birlikte kullanılması gereken deyimsel tekniklere odaklanan tek cevaptır ve bu da bu soru için en iyi cevaptır. Doğru kodla doğru cevabı almayı öğrenmek ( yanlış kodla doğru cevap yerine - yani verimsiz, ölçeklendirilmez, belirli verilere çok uygun değildir) öğrenme pandalarının (ve genel olarak verilerin) büyük bir parçasıdır.
LinkBerest

3
Sanırım for döngüsüne haksızlık ediyorsun, testlerimde liste kavrayışından biraz daha yavaş olduklarını görüyorsun. Hile zip(df['A'], df['B'])yerine döngü için df.iterrows().
Kusursuz Gece

2
@ImperishableNight Hiç değil; bu yazının amacı genel olarak yinelemeyi kınamak değil - iterrows()daha iyi alternatifler varsa ve olduğunda, yinelemenin kullanımını kınamak ve dolaylı olarak kınamaktır. forkendi başlarına döngüler uygundur, ancak yinelemeli olarak elemanlar arası dönüşümler gerçekleştiriyorsanız liste anlaşmaları daha iyidir.
cs95

1
@sdbbs var, verilerinizi sıralamak için sort_values ​​kullanın, ardından sonuçta to_string () öğesini çağırın.
cs95

1
Liste Anlamaları altında, "birden çok sütun üzerinde yineleme" örneği bir uyarı gerektirir: DataFrame.valuesher sütunu ortak bir veri türüne dönüştürür. DataFrame.to_numpy()bunu da yapar. Neyse ki zipherhangi bir sayıda sütunla kullanabiliriz.
David Wasserman

397

Öncelikle bir DataFrame'deki satırlar üzerinde gerçekten yineleme yapmanız gerekip gerekmediğini düşünün. Alternatifler için bu cevaba bakınız .

Hala satırlar üzerinden yineleme yapmanız gerekiyorsa, aşağıdaki yöntemleri kullanabilirsiniz. Diğer cevaplarda belirtilmeyen bazı önemli uyarılara dikkat edin.

itertuples() daha hızlı olması gerekiyordu iterrows()

Ancak dokümanlara göre şu anda dikkat edin (şu anda pandalar 0.24.2):

  • iterrows: dtypesatırdan satıra eşleşmeyebilir

    İterrows her satır için Serisi döndürür olduğundan, korumaz sıralar (dtypes DataFrames için sütunlar arasında korunur) karşısında dtypes. Satırlar üzerinde yineleme yaparken dtypes'leri korumak için, değerlerin adlandırılmış başlıklarını döndüren ve genellikle iterrows'dan () çok daha hızlı olan itertuples () kullanmak daha iyidir

  • iterrows: Satırları değiştirmeyin

    Sen gerektiğini değiştirmek asla baştan yineleme olan bir şey. Bunun her durumda çalışması garanti edilmez. Veri türlerine bağlı olarak, yineleyici bir görünüm değil bir kopya döndürür ve ona yazmanın bir etkisi olmaz.

    Kullanım DataFrame.apply () yerine:

    new_df = df.apply(lambda x: x * 2)
  • itertuples:

    Sütun adları geçersiz Python tanımlayıcılarıysa, yinelenirse veya bir alt çizgi ile başlarsa konum adlarıyla yeniden adlandırılır. Çok sayıda sütunla (> 255) normal tuples döndürülür.

Daha fazla ayrıntı için yineleme ile ilgili panda dokümanlarına bakın.


4
Tamamlandıktan bu kadar uzun bir süre sonra bu konuyu okuyan birinden küçük bir soru: df.apply () verimlilik açısından itertuples ile nasıl kıyaslanır?
Raul Guarini

4
Not: for row in df[['c1','c2']].itertuples(index=True, name=None):Satır yineleyiciye yalnızca belirli sütunları dahil etmek gibi bir şey de söyleyebilirsiniz .
Brian Burns

12
Bunun yerine, getattr(row, "c1")sadece kullanabilirsiniz row.c1.
viraptor

1
Bunun getattr(row, "c1")yerine, row.c1herhangi bir performans avantajını kaybederseniz itertuplesve aslında bir dize yoluyla özelliğe ulaşmak gerekiyorsa, bunun yerine iterrows kullanmanız gerektiğinden yaklaşık% 90 eminim .
Noctiphobia

3
Bu soru üzerine tökezledim, çünkü split-Apply-combine olduğunu bilsem de, hala gerçekten bir DataFrame (soru belirttiği gibi) üzerinde yineleme gerekiyordu . Herkesin geliştirmek için lüksü yoktur numbave cython(aynı dokümanlar "Önce Python'da her zaman optimize etmeye değer" der). Bu cevabı, diğer cevapların hiçbiri bu uyarılardan bahsetmediğinden diğerlerinin (bazen sinir bozucu) sorunlardan kaçınmasına yardımcı olmak için yazdım. Hiç kimseyi yanıltmak ya da "bu doğru şey" demek asla niyetim değildi. Cevabı geliştirdim.
viddik13

201

Kullanmalısınız df.iterrows(). Her ne kadar satır satır yineleme Seriesnesnelerin oluşturulması gerektiğinden özellikle etkili değildir .


12
Bu, DataFrame'i bir numpy dizisine (.values ​​aracılığıyla) dönüştürmekten ve doğrudan dizi üzerinde işlem yapmaktan daha mı hızlı? Ben de aynı sorun var, ama numpy dizi dönüştürme ve sonra cython kullanarak sona erdi.
vgoklani

12
@vgoklani Satır satır yineleme verimsizse ve nesne olmayan bir numpy diziniz varsa, hemen hemen kesinlikle ham numpy dizisini kullanmak, özellikle çok satırlı diziler için daha hızlı olacaktır. kesinlikle gerekmedikçe satırları yinelemekten kaçınmalısınız
Phillip Cloud

7
Ben df.iterrows (), df.itertuples () ve zip (df ['a'], df ['b']) için zaman tüketimi üzerinde biraz test yaptım ve sonucu başka bir cevap gönderdi soru: stackoverflow.com/a/34311080/2142098
Richard Wong

154

iterrows()İyi bir seçenek olsa da, bazen itertuples()çok daha hızlı olabilir:

df = pd.DataFrame({'a': randn(1000), 'b': randn(1000),'N': randint(100, 1000, (1000)), 'x': 'x'})

%timeit [row.a * 2 for idx, row in df.iterrows()]
# => 10 loops, best of 3: 50.3 ms per loop

%timeit [row[1] * 2 for row in df.itertuples()]
# => 1000 loops, best of 3: 541 µs per loop

5
İki örneğinizdeki zaman farkının çoğu, .iterrows () komutu için etiket tabanlı indeksleme ve .itertuples () komutu için tamsayı tabanlı indeksleme kullandığınızdan kaynaklanıyor gibi görünüyor.
Alex

2
Finans veri tabanlı bir veri çerçevesi (zaman damgası ve 4x kayan nokta) için, itertuples benim makinemde olduğundan 19,57 kat daha hızlıdır. Sadece for a,b,c in izip(df["a"],df["b"],df["c"]:neredeyse eşit derecede hızlı.
harbun

7
Neden daha hızlı olduğunu açıklayabilir misiniz?
Abe Miessler

4
@AbeMiessler iterrows()her veri satırını bir Seriye koyar , oysa itertuples()bunu yapmaz.
miradulo

3
dfBir sözlükten oluşturulduğundan , sütunların sırasının aslında belirsiz olduğunu, bu nedenle row[1]sütunlardan herhangi birine başvurabileceğini unutmayın. Anlaşılan o ki tamsayı float sütunlar için kabaca aynıdır.
Brian Burns

88

Ayrıca df.apply(), satırlar üzerinde yineleme yapmak ve bir işlev için birden çok sütuna erişmek için de kullanabilirsiniz .

dokümanlar: DataFrame.apply ()

def valuation_formula(x, y):
    return x * y * 0.5

df['price'] = df.apply(lambda row: valuation_formula(row['x'], row['y']), axis=1)

Df ['price'] veri çerçevesindeki bir sütun adını mı ifade ediyor? Bir csv dosyasındaki birkaç sütundan benzersiz değerlere sahip bir sözlük oluşturmaya çalışıyorum. Mantığınızı benzersiz anahtarlar ve değerlerle bir sözlük oluşturmak için kullandım ve TypeError'u
SRS

Kod: df ['Workclass'] = df.apply (lambda satırı: dic_update (satır), eksen = 1) satır sonu id = 0 satır sonu def dic_update (satır): satır dic'de değilse: dic [satır] = id id = id + 1
SRS

Boş ver, anladım. İşlev çağrı hattı df_new = df ['Workclass'] olarak değiştirildi Uygula (aynı şey)
SRS

2
Eksenin varsayılan olarak 0 olması kötüdür
zthomas.nc

9
applySatırlar üzerinde "iteratite" yapmadığına dikkat edin , bunun yerine satır-bazlı bir fonksiyon uygular. Örneğin, farklı satırlardaki değerleri karşılaştırırken (örneğin, yinelemeden başka bir şey yapamazsınız) gerçekten yinelemelere ve girintilere ihtiyacınız varsa yukarıdaki kod çalışmaz .
gented

82

Df.iloc işlevini aşağıdaki gibi kullanabilirsiniz:

for i in range(0, len(df)):
    print df.iloc[i]['c1'], df.iloc[i]['c2']

1
Bunun kaşıntı veya kaşıntı lehine bundan kaçınması gerektiğini biliyorum, ama nedenini bilmek ilginç olurdu. Düşüncesi olan var mı?
rocarvaj

12
Bu, veri türlerini korumak isteyip istemediğinizi bildiğim tek geçerli tekniktir ve ayrıca sütunları ada göre de belirtir. itertuplesveri türlerini korur, ancak sevmediği herhangi bir addan kurtulur. iterrowstam tersini yapar.
Ken Williams

6
Basit ve etkileyici bir şey yapmak için panda veri yapılarının kendine özgü ifadelerini geçmeye çalışarak saatler geçirdik. Bu okunabilir kod ile sonuçlanır.
Sean Anderson

İken for i in range(df.shape[0])benim uygulama için yukarıda biraz yukarı bu yaklaşımı hızlandırmak olabilir, bu iterrows daha yavaş 3.5x hakkında hala () yaklaşımı.
Kim Miller

Büyük Datafrmes'de my_iter = df.itertuples(), hafızayı iki katına çıkarmak ve kopyalamak için çok zaman harcadığı için bu daha iyi görünüyor . için aynı iterrows().
Bastiaan

33

Ben satır ve sütunlarda yineleme nasıl arıyordu ve burada sona erdi:

for i, row in df.iterrows():
    for j, column in row.iteritems():
        print(column)

18

Uygulayan kendi yineleyicinizi yazabilirsiniz namedtuple

from collections import namedtuple

def myiter(d, cols=None):
    if cols is None:
        v = d.values.tolist()
        cols = d.columns.values.tolist()
    else:
        j = [d.columns.get_loc(c) for c in cols]
        v = d.values[:, j].tolist()

    n = namedtuple('MyTuple', cols)

    for line in iter(v):
        yield n(*line)

Bu doğrudan ile karşılaştırılabilir pd.DataFrame.itertuples. Aynı görevi daha verimli bir şekilde yapmayı hedefliyorum.


İşlevimle birlikte verilen veri çerçevesi için:

list(myiter(df))

[MyTuple(c1=10, c2=100), MyTuple(c1=11, c2=110), MyTuple(c1=12, c2=120)]

Veya pd.DataFrame.itertuples:

list(df.itertuples(index=False))

[Pandas(c1=10, c2=100), Pandas(c1=11, c2=110), Pandas(c1=12, c2=120)]

Kapsamlı bir test
Tüm sütunları kullanılabilir hale getirmeyi ve sütunları alt ayarlamayı test ediyoruz.

def iterfullA(d):
    return list(myiter(d))

def iterfullB(d):
    return list(d.itertuples(index=False))

def itersubA(d):
    return list(myiter(d, ['col3', 'col4', 'col5', 'col6', 'col7']))

def itersubB(d):
    return list(d[['col3', 'col4', 'col5', 'col6', 'col7']].itertuples(index=False))

res = pd.DataFrame(
    index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    columns='iterfullA iterfullB itersubA itersubB'.split(),
    dtype=float
)

for i in res.index:
    d = pd.DataFrame(np.random.randint(10, size=(i, 10))).add_prefix('col')
    for j in res.columns:
        stmt = '{}(d)'.format(j)
        setp = 'from __main__ import d, {}'.format(j)
        res.at[i, j] = timeit(stmt, setp, number=100)

res.groupby(res.columns.str[4:-1], axis=1).plot(loglog=True);

resim açıklamasını buraya girin

resim açıklamasını buraya girin


2
Kodu okumak istemeyen insanlar için: mavi çizgi intertuples, turuncu çizgi, bir verim bloğu aracılığıyla bir yineleyicinin listesidir. interrowskarşılaştırılmaz.
James L.

18

Nasıl verimli bir şekilde tekrarlanır?

Gerçekten bir panda veri çerçevesini yinelemeniz gerekiyorsa, muhtemelen iterrows () kullanmaktan kaçınmak isteyeceksiniz . Farklı yöntemler vardır ve her zamanki iterrows()en iyisi olmaktan uzaktır. itertuples () 100 kat daha hızlı olabilir.

Kısacası:

  • Genel bir kural olarak, kullanın df.itertuples(name=None). Özellikle, sabit bir sayı sütununuz ve 255'ten az sütununuz olduğunda. Bakınız nokta (3)
  • Aksi takdirde, df.itertuples()sütunlarınızda boşluk veya '-' gibi özel karakterler varsa kullanın . Bakınız nokta (2)
  • Son itertuples()kareyi kullanarak veri karenizde garip sütunlar olsa bile kullanmak mümkündür . Bkz. Nokta (4)
  • Yalnızca iterrows()önceki çözümleri yapamıyorsanız kullanın . Bakınız nokta (1)

Panda veri çerçevesinde satırlar üzerinde yineleme yapmak için farklı yöntemler:

Milyon satır ve 4 sütundan oluşan rastgele bir veri çerçevesi oluşturun:

    df = pd.DataFrame(np.random.randint(0, 100, size=(1000000, 4)), columns=list('ABCD'))
    print(df)

1) Her zamanki iterrows()uygun ama lanet yavaş:

start_time = time.clock()
result = 0
for _, row in df.iterrows():
    result += max(row['B'], row['C'])

total_elapsed_time = round(time.clock() - start_time, 2)
print("1. Iterrows done in {} seconds, result = {}".format(total_elapsed_time, result))

2) Varsayılan itertuples()zaten çok daha hızlıdır, ancak gibi sütun adlarıyla çalışmaz My Col-Name is very Strange(sütunlarınız tekrarlanırsa veya bir sütun adı basitçe bir python değişken adına dönüştürülemiyorsa bu yöntemden kaçınmalısınız) .:

start_time = time.clock()
result = 0
for row in df.itertuples(index=False):
    result += max(row.B, row.C)

total_elapsed_time = round(time.clock() - start_time, 2)
print("2. Named Itertuples done in {} seconds, result = {}".format(total_elapsed_time, result))

3) itertuples()name = None kullanan varsayılan , daha hızlıdır, ancak sütun başına bir değişken tanımlamanız gerektiği için gerçekten uygun değildir.

start_time = time.clock()
result = 0
for(_, col1, col2, col3, col4) in df.itertuples(name=None):
    result += max(col2, col3)

total_elapsed_time = round(time.clock() - start_time, 2)
print("3. Itertuples done in {} seconds, result = {}".format(total_elapsed_time, result))

4) Son olarak, adlandırılan itertuples()önceki noktadan daha yavaştır, ancak sütun başına bir değişken tanımlamanız gerekmez ve gibi sütun adlarıyla çalışır My Col-Name is very Strange.

start_time = time.clock()
result = 0
for row in df.itertuples(index=False):
    result += max(row[df.columns.get_loc('B')], row[df.columns.get_loc('C')])

total_elapsed_time = round(time.clock() - start_time, 2)
print("4. Polyvalent Itertuples working even with special characters in the column name done in {} seconds, result = {}".format(total_elapsed_time, result))

Çıktı:

         A   B   C   D
0       41  63  42  23
1       54   9  24  65
2       15  34  10   9
3       39  94  82  97
4        4  88  79  54
...     ..  ..  ..  ..
999995  48  27   4  25
999996  16  51  34  28
999997   1  39  61  14
999998  66  51  27  70
999999  51  53  47  99

[1000000 rows x 4 columns]

1. Iterrows done in 104.96 seconds, result = 66151519
2. Named Itertuples done in 1.26 seconds, result = 66151519
3. Itertuples done in 0.94 seconds, result = 66151519
4. Polyvalent Itertuples working even with special characters in the column name done in 2.94 seconds, result = 66151519

Bu makale, kaşıntılar ve kaşıntılar arasında çok ilginç bir karşılaştırma


14

Birindeki tüm satırları döngüye sokmak için dataframeşunları kullanabilirsiniz:

for x in range(len(date_example.index)):
    print date_example['Date'].iloc[x]

1
Bu zincirleme indeksleme. Bunu önermiyorum.
cs95

@ cs95 Bunun yerine ne önerirsiniz?
19:19

Bu işi yapmak istiyorsanız, tarih sütununun (döngü dışında) tamsayı dizin konumunu almak için df.columns.get_loc öğesini arayın, ardından içeride tek bir iloc dizinleme çağrısı kullanın.
cs95

14
 for ind in df.index:
     print df['c1'][ind], df['c2'][ind]

1
büyük bir veri çerçevesinde (örneğin milyonlarca satır) kullanıldığında bu seçeneğin performansı nasıl?
Bazyli Debowski

Dürüst olmak gerekirse, tam olarak bilmiyorum, en iyi cevapla karşılaştırıldığında geçen sürenin yaklaşık aynı olacağını düşünüyorum, çünkü her iki durumda da "inşaat" için. Ancak bazı durumlarda bellek farklı olabilir.
Grag2015

4
Bu zincirleme indeksleme. Bunu kullanmayın!
cs95

7

Bazen yararlı bir desen:

# Borrowing @KutalmisB df example
df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])
# The to_dict call results in a list of dicts
# where each row_dict is a dictionary with k:v pairs of columns:value for that row
for row_dict in df.to_dict(orient='records'):
    print(row_dict)

Sonuç:

{'col1':1.0, 'col2':0.1}
{'col1':2.0, 'col2':0.2}

6

Döngü için bir tüm satırları dataframeve kullanımı , her sıranın değerlerine uygun , namedtuplesdönüştürülebilir ndarrays. Örneğin:

df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])

Satırların üzerinde yineleme:

for row in df.itertuples(index=False, name='Pandas'):
    print np.asarray(row)

sonuç:

[ 1.   0.1]
[ 2.   0.2]

Eğer lütfen unutmayın index=True, endeks başlığın ilk öğe olarak ekleniyor bazı uygulamalar için istenmeyen bir durum olabilir.


5

Seri değil, DataFrame alırken fırlatma satırlarını yinelemenin bir yolu vardır. Herkes DataFrame olarak döndürülecek satır için bir liste olarak dizin geçirebilirsiniz söyleyen görmüyorum:

for i in range(len(df)):
    row = df.iloc[[i]]

Çift parantez kullanımına dikkat edin. Bu, tek satırlı bir DataFrame döndürür.


Bu, sıralamadan sonra bir veri çerçevesinde n'inci en büyük satırı elde etmek için çok yararlı oldu. Teşekkürler!
Jason Harrison

3

Değerleri görüntülemek ve değiştirmek için kullanırım iterrows(). For döngüsü ve tuple unpacking kullanarak (örneğe bakın:) i, row, ben rowsadece değeri görüntülemek için kullanın ive locdeğerleri değiştirmek istediğinizde yöntemle kullanın . Önceki yanıtlarda belirtildiği gibi, burada yinelediğiniz bir şeyi değiştirmemelisiniz.

for i, row in df.iterrows():
    df_column_A = df.loc[i, 'A']
    if df_column_A == 'Old_Value':
        df_column_A = 'New_value'  

Burada rowdöngü içinde, bu satırın bir kopyası değil, bir kopyasıdır. Bu nedenle, row['A'] = 'New_Value'DataFrame değiştirmeyecek gibi bir şey yazmamalısınız. Ancak, işi yapmak için DataFrame'i kullanabilir ive locbelirleyebilirsiniz.


2

Yanıtlayan tarafa geç kaldığımı biliyorum, ama sadece @ cs95'in yukarıdaki cevaba eklemek istedim, ki kabul edilen cevap olmalı. Onun cevabında, pandaların vektörleşmesinin, veri çerçeveleri ile bir şeyler hesaplamak için diğer pandaların yöntemlerinden çok daha iyi performans gösterdiğini gösteriyor.

Veri çerçevesini ilk önce bir numpy dizisine dönüştürüp vektörleştirmeyi kullanırsanız, panda veri çerçevesi vektörleştirmesinden bile daha hızlı olduğunu (ve bunu bir veri çerçevesi serisine geri döndürme süresini içerdiğini) eklemek istedim.

@ Cs95'in karşılaştırma koduna aşağıdaki işlevleri eklerseniz, bu oldukça belirgin hale gelir:

def np_vectorization(df):
    np_arr = df.to_numpy()
    return pd.Series(np_arr[:,0] + np_arr[:,1], index=df.index)

def just_np_vectorization(df):
    np_arr = df.to_numpy()
    return np_arr[:,0] + np_arr[:,1]

resim açıklamasını buraya girin


1

Daha numpyda yüksek hız artışları için indeksleme de yapabilirsiniz . Gerçekten yineleyici değildir, ancak belirli uygulamalar için yinelemeden çok daha iyi çalışır.

subset = row['c1'][0:5]
all = row['c1'][:]

Ayrıca bunu bir diziye yayınlamak da isteyebilirsiniz. Bu dizinlerin / seçimlerin zaten Numpy dizileri gibi davranması gerekiyordu, ancak sorunla karşılaştım ve yayın yapmam gerekiyordu

np.asarray(all)
imgs[:] = cv2.resize(imgs[:], (224,224) ) #resize every image in an hdf5 file

1

Panda veri çerçevesinde satırları yinelemenin birçok yolu vardır. Çok basit ve sezgisel bir yol:

df=pd.DataFrame({'A':[1,2,3], 'B':[4,5,6],'C':[7,8,9]})
print(df)
for i in range(df.shape[0]):
    # For printing the second column
    print(df.iloc[i,1])
    # For printing more than one columns
    print(df.iloc[i,[0,2]])

0

Bu örnek, veri çerçevesindeki her bir basamağı izole etmek için iloc kullanır.

import pandas as pd

 a = [1, 2, 3, 4]
 b = [5, 6, 7, 8]

 mjr = pd.DataFrame({'a':a, 'b':b})

 size = mjr.shape

 for i in range(size[0]):
     for j in range(size[1]):
         print(mjr.iloc[i, j])

0

Bazı kütüphaneler (örneğin kullandığım bir Java birlikte çalışma kitaplığı) değerlerin, örneğin veri akışı halinde, bir seferde bir sırada geçirilmesini gerektirir. Akış doğasını çoğaltmak için, veri çerçevesi değerlerimi tek tek 'akışla', zaman zaman kullanışlı olan aşağıdakileri yazdım.

class DataFrameReader:
  def __init__(self, df):
    self._df = df
    self._row = None
    self._columns = df.columns.tolist()
    self.reset()
    self.row_index = 0

  def __getattr__(self, key):
    return self.__getitem__(key)

  def read(self) -> bool:
    self._row = next(self._iterator, None)
    self.row_index += 1
    return self._row is not None

  def columns(self):
    return self._columns

  def reset(self) -> None:
    self._iterator = self._df.itertuples()

  def get_index(self):
    return self._row[0]

  def index(self):
    return self._row[0]

  def to_dict(self, columns: List[str] = None):
    return self.row(columns=columns)

  def tolist(self, cols) -> List[object]:
    return [self.__getitem__(c) for c in cols]

  def row(self, columns: List[str] = None) -> Dict[str, object]:
    cols = set(self._columns if columns is None else columns)
    return {c : self.__getitem__(c) for c in self._columns if c in cols}

  def __getitem__(self, key) -> object:
    # the df index of the row is at index 0
    try:
        if type(key) is list:
            ix = [self._columns.index(key) + 1 for k in key]
        else:
            ix = self._columns.index(key) + 1
        return self._row[ix]
    except BaseException as e:
        return None

  def __next__(self) -> 'DataFrameReader':
    if self.read():
        return self
    else:
        raise StopIteration

  def __iter__(self) -> 'DataFrameReader':
    return self

Hangi kullanılabilir:

for row in DataFrameReader(df):
  print(row.my_column_name)
  print(row.to_dict())
  print(row['my_column_name'])
  print(row.tolist())

Yinelenen satırlar için değerleri / ad eşlemesini korur. Açıkçası, yukarıda belirtildiği gibi Apply ve Cython kullanmaktan çok daha yavaştır, ancak bazı durumlarda gereklidir.


0

Kısacası

  • Mümkünse vektörleştirmeyi kullanın
  • İşlem vektörleştirilemiyorsa - liste anlamalarını kullanın
  • Tüm satırı temsil eden tek bir nesneye ihtiyacınız varsa - itertuples kullanın
  • Yukarıdakiler çok yavaşsa - swifter'i deneyin.
  • Hala çok yavaşsa - Cython rutinini deneyin

Ayrıntılar bu video

Karşılaştırma Panda DataFrame'deki satırlar üzerinde yinelemenin karşılaştırması

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.