PandasでDataFrameの行を反復処理する方法

python pandas rows dataframe


私はパンダの DataFrame を持っています:

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

Output:

   c1   c2
0  10  100
1  11  110
2  12  120

ここで、このフレームの行を繰り返し処理したいと思います。各行について、その要素(セル内の値)に列の名前でアクセスできるようにしたいと思います。例えば、以下のようにします。

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

パンダでも可能なのかな?

私はこの同様の質問を見つけました。しかし、それは私に必要な答えを与えません。たとえば、そこで使用することをお勧めします。

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

or

for row in df.iterrows():

しかし、私は row オブジェクトが何であるか、そしてそれをどのように操作できるのか理解していません。




Answer 1 waitingkuo


DataFrame.iterrowsは、インデックスと行の両方を生成するジェネレーターです。

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



Answer 2 cs95


PandasでDataFrameの行を反復処理するには?

回答:しないでください*

パンダでの反復はアンチパターンであり、他のすべてのオプションを使い果たした場合にのみ行うべきです。名前に「 iter 」が含まれる関数を数千行以上使用しないでください。使用すると、多くの待機に慣れる必要があります。

DataFrameを印刷しますか? DataFrame.to_string()使用します。

何かを計算しますか?その場合は、次の順序でメソッドを検索します(ここからリストを変更します)。

  1. Vectorization
  2. サイトンルーチン
  3. リスト内包表記(バニラ for ループ)
  4. DataFrame.apply() :i)cythonで実行できる削減、ii)python空間での反復
  5. DataFrame.itertuples() および iteritems()
  6. DataFrame.iterrows()

iterrowsitertuples (どちらもこの質問に対する回答で多くの票を獲得している)は、シーケンシャル処理用の行オブジェクト/名前タプルの生成など、非常にまれな状況で使用する必要があります。

当局への訴え
反復のドキュメントページには、次のような巨大な赤い警告ボックスがあります。

パンダオブジェクトの反復処理は一般的に遅いです。多くの場合、手動で行を反復処理する必要はありません。

*実際には、「しない」よりも少し複雑です。 df.iterrows() がこの質問への正しい答えですが、「演算をベクトル化する」のがより適切です。反復を回避できない状況があることを認めます(たとえば、結果が前の行に対して計算された値に依存する操作など)。ただし、いつライブラリを使用するかを理解するには、ある程度の知識が必要です。反復的な解決策が必要かどうかわからない場合は、おそらく必要ありません。PS:この回答を書く私の理論的根拠について詳しく知るには、一番下までスキップしてください。


ループよりも高速:ベクトル化Cython

多数の基本的な演算と計算は、パンダによって(NumPyまたはCythonized関数のいずれかによって)「ベクトル化」されます。これには、算術、比較、(ほとんどの)削減、再形成(ピボットなど)、結合、およびgroupby操作が含まれます。Essential Basic Functionalityのドキュメントを参照して、問題に適したベクトル化された方法を見つけてください。

存在しない場合は、カスタムcython拡張機能を使用して独自に作成してください。


次善の策:リスト内包表記

リスト内包表記は、1)利用可能なベクトル化されたソリューションがない場合、2)パフォーマンスは重要であるが、コードをCythonizeする面倒をたどるほど重要ではない場合、および3)要素ごとの変換を実行する場合は、次の呼び出し先にする必要があります。あなたのコードに。多くの一般的なパンダのタスクでは、リスト内包表記が十分に速い(場合によってはさらに速い)ことを示唆する十分な証拠があります。

式はシンプルです。

# 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
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].values]

ビジネスロジックを関数にカプセル化できれば、それを呼び出すリスト内包を使うことができます。生のPythonのシンプルさとスピードで、任意に複雑なものを動作させることができます。


わかりやすい例

2つのパンダ列 A + B を追加する簡単な例で違いを示しましょう。これはベクトル化可能な操作であるため、前述の方法のパフォーマンスと簡単に対比できます。

enter image description here

ベンチマークコード、参考までに。

しかし、このように一概には言えません。ある操作に最適な方法は何か」という答えは、「データに依存する」ということもあります。私のアドバイスは、一つの方法に落ち着く前に、データ上で様々なアプローチをテストしてみることです。


続きを読む

* Pandas文字列メソッドは、シリーズで指定されているが各要素で動作するという意味で「ベクトル化」されています。文字列操作は本質的にベクトル化が難しいため、基礎となるメカニズムは依然として反復的です。


この回答を書いた理由

私が新しいユーザーから気づく一般的な傾向は、「どのようにしてdfを反復してXを実行できるか?」という形式の質問をすることです。forループ内で何かをしている間に iterrows() を呼び出すコードを表示します。これが理由です。ベクトル化の概念を紹介されていないライブラリの新しいユーザーは、データを繰り返し処理して何かを行うときに問題を解決するコードを想定している可能性があります。 DataFrameを反復処理する方法がわからないため、彼らが最初に行うことは、それをGoogleにして、この質問でここに到達することです。次に、受け入れられた答えがどのように伝えられるかを確認し、目を閉じて、反復が適切でないかどうかを最初に確認することなくこのコードを実行します。

この回答の目的は、反復処理が必ずしもすべての問題の解決策ではないこと、より良い、より速く、より慣用的な解決策が存在する可能性があること、そしてそれらを探求するために時間を投資する価値があることを新しいユーザに理解してもらうことにあります。イテレーション対ベクトル化の戦争を始めようとしているわけではありませんが、新しいユーザがこのライブラリを使って問題の解決策を開発する際には、情報を得て欲しいと思っています。




Answer 3 viddik13


最初に、本当にDataFrameの行を反復処理する必要があるかどうかを検討します。代替案については、この回答を参照してください。

それでも行を反復処理する必要がある場合は、以下のメソッドを使用できます。他の回答には記載されていないいくつかの重要な注意事項に注意してください 。

itertuples() よりも速くすることになっている iterrows()

しかし、ドキュメント(現時点ではパンダ0.24.2)によると、注意が必要です。

  • iterrows: dtype が行ごとに一致しない場合がある

    iterrowsは各行のSeriesを返すため、行全体のdtypeは保持されません(dtypeはデータフレームの列全体で保持されます)。行を反復するときにdtypeを保持するには、値の名前付きタプルを返し、一般にiterrows()よりも高速なitertuples()を使用することをお勧めします。

  • イテローを使用します。行を変更しない

    反復しているものを変更してはいけません。これは、すべての場合に機能するとは限りません。データ型に応じて、イテレータはビューではなくコピーを返し、そこへの書き込みは効果がありません。

    代わりにDataFrame.apply()を使用します。

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

    列名は、それらが無効なPython識別子であるか、繰り返されるか、アンダースコアで始まる場合、位置名に名前変更されます。列数が多い(> 255)と、通常のタプルが返されます。

詳細については、繰り返しに関するパンダのドキュメントを参照してください。




Answer 4 Wes McKinney


df.iterrows() を使用する必要があります。ただし、 Series オブジェクトを作成する必要があるため、行ごとの反復は特に効率的ではありません。




Answer 5 e9t


一方で iterrows() 、良いオプションです時々 itertuples() はるかに高速になります

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