パンダのデータフレームの行を反復する方法は?


1951

私はDataFrameパンダから来ました:

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

出力:

   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():

または

for row in df.iterrows():

しかし、私はrowオブジェクトが何であるか、そしてどうやってそれを扱うことができるのか分かりません。


11
df.iteritems()は、行ではなく列を反復します。したがって、行を反復させるには、転置する必要があります( "T")。つまり、行と列を相互に変更します(対角線を反映)。その結果、df.T.iteritems()を使用すると、元のデータフレームを行全体で効果的に反復できます
Stefan Gruenwald

12
あなたがこのスレッドに不慣れで、パンダの初心者である場合は、繰り返さないでください!! データフレームの反復はアンチパターンであり、多くの待機に慣れる必要がない限り、行うべきではありません。あなたがやろうとしていることに応じて、おそらくはるかに優れた代替案があります。iter*関数は非常にまれな状況で使用する必要があります。また、関連しています。
cs95

19
cs95が言うこととは対照的に、データフレームを反復処理したい完全に細かい理由があるので、新しいユーザーは落胆する必要はありません。1つの例は、各行の値を入力として使用してコードを実行する場合です。また、データフレームがかなり小さい場合(たとえば、アイテム数が1000未満の場合)、パフォーマンスはそれほど問題になりません。
oulenz

1
@oulenz:奇妙な理由で、APIの設計目的(高性能データ変換)でAPIを使用することに直面したい場合は、私のゲストになってください。ただし、少なくとも、を使用しないiterrowsでください。DataFrameを反復するより良い方法があり、その時点でリストのリストを反復することもできます。DataFrameを繰り返し処理する以外に何もしていない段階にいる場合、DataFrameを使用してもまったくメリットはありません(DataFrameを繰り返し処理することが唯一の処理であると仮定すると)。ちょうど私の2c。
cs95

8
@oulenzの2番目です。私が知る限りpandas、データセットが小さい場合でも、csvファイルの読み取りを選択する必要があります。APIでデータを操作する方が簡単にプログラミングできます
Chris

回答:


2639

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

207
注:「iterrowsは各行のSeriesを返すため、行全体のdtype 保持されません。」また、「繰り返しているものを変更しはなりません。」よると、パンダ0.19.1ドキュメント
viddik13

3
@ viddik13ありがとうございます。そのため、数値431341610650がと読まれるようなケースに遭遇しました4.31E+11。dtypesを保持する方法はありますか?
アジズアルト2017

26
itertuples以下で説明するように、@ AzizAltoを使用します。pandas.pydata.org/pandas-docs/stable/generated/…
Axel

101
イテローは使用しないでください。Itertuplesはより高速で、データ型を保持します。詳細
ジェームズL.

11
ドキュメントから:「パンダオブジェクトを反復処理することは一般的に遅いです。多くの場合、行を手動で反復処理する必要はありません[...]」。あなたの答えは正しいです(質問の文脈では)が、これについてはどこにも言及していないため、あまり良いものではありません。
cs95

460

パンダのデータフレームの行を反復する方法は?

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

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

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

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

  1. ベクトル化
  2. Cythonルーチン
  3. リスト内包表記(バニラforループ)
  4. DataFrame.apply():i)cythonで実行できる削減、ii)python空間での反復
  5. DataFrame.itertuples() そして iteritems()
  6. DataFrame.iterrows()

iterrowsそしてitertuples(この質問への回答に多くの票を受信の両方)は、実際にこれらの機能はするのに有用である唯一のもので順次処理のために行オブジェクト/ nametuplesを生成するような非常にまれな状況で使用されるべきです。

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

通常、パンダオブジェクトの反復処理は低速です。多くの場合、行を手動で反復する必要はありません[...]。

*実際には、「しない」よりも少し複雑です。df.iterrows()はこの質問に対する正しい答えですが、「opize your ops」の方が適しています。反復を回避できない状況があることを認めます(たとえば、結果が前の行に対して計算された値に依存する操作など)。ただし、いつライブラリを使用するかを理解するには、ある程度の知識が必要です。反復的な解決策が必要かどうかわからない場合は、おそらく必要ありません。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 - 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'])]

ビジネスロジックを関数にカプセル化できる場合は、それを呼び出すリスト内包表記を使用できます。素のpythonのシンプルさとスピードにより、任意に複雑なものを機能させることができます。

警告
リストの理解は、データが扱いやすいことを前提としています。つまり、データ型が一貫していて、NaNがないということですが、これは常に保証されるわけではありません。

  1. 最初の方法はより明白ですが、NaNを処理するときは、組み込みのパンダメソッドが存在する場合はそれらを優先するか(コーナーケース処理ロジックがはるかに優れているため)、またはビジネスロジックに適切なNaN処理ロジックが含まれていることを確認します。
  2. 混合データ型を扱う場合、後者は暗黙的にデータを最も一般的な型にアップキャストするのではzip(df['A'], df['B'], ...)なく、反復する必要がありますdf[['A', 'B']].to_numpy()。例として、Aが数値でBが文字列の場合、to_numpy()は配列全体を文字列にキャストしますが、これは希望と異なる場合があります。幸いzip、列を一緒にpingすることが、これに対する最も簡単な回避策です。

* YMMVに概説さの理由のために警告を上記セクション。


明白な例

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

ここに画像の説明を入力してください

参考のために、ベンチマークコード。

ただし、これが常に乾燥して乾燥しているとは限りません。「操作に最適な方法は何か」に対する答えは、「データに依存する」場合があります。私のアドバイスは、データを解決する前に、データに対するさまざまなアプローチをテストすることです。


参考文献

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


なぜこの答えを書いたのか

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

この回答の目的は、反復が必ずしもすべての問題の解決策であるとは限らず、より優れた、より速く、より慣用的な解決策が存在する可能性があること、およびそれらを探索することに時間を費やす価値があることを新しいユーザーが理解できるようにすることです。私はイテレーションとベクトル化の戦争を始めようとはしていませんが、このライブラリーに関する問題の解決策を開発するときに、新しいユーザーに知らせたいと思います。


24
これは、パンダで使用すべき慣用的な手法に焦点を当てた唯一の回答であり、この質問に対する最良の回答です。取得するために学ぶ権利 と答えを コード(代わりの と答え 間違っ コード -すなわち非効率的な、あまりにも特定のデータに収まらないスケールは、ん)(一般に、データ)パンダの学習の大部分です。
LinkBerest

3
私のテストではforループがリストの理解よりも少し遅いだけなので、forループに不公平だと思います。コツはのzip(df['A'], df['B'])代わりにループすることですdf.iterrows()
不可解な夜

2
@ImperishableNightまったくありません。この投稿の目的は、一般的に反復を非難することではありません。それは、の使用を明確に非難し、iterrows()より良い代替案が存在する場合は暗黙的に反復を非難することです。forループ自体は問題ありませんが、要素単位の変換を繰り返し実行する場合は、リスト内包表記の方が適しています。
cs95

1
@sdbbsがあります。sort_valuesを使用してデータをソートし、結果に対してto_string()を呼び出します。
cs95

1
リスト内包で、「複数の列の反復」の例では注意が必要DataFrame.valuesです。すべての列を共通のデータ型に変換します。 DataFrame.to_numpy()これも行います。さいわいzip、任意の数の列で使用できます。
David Wasserman、

397

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

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

itertuples() よりも速いはずです iterrows()

ただし、ドキュメントによれば(現時点ではパンダ0.24.2)、注意してください。

  • iterrows:dtype行ごとに一致しない可能性があります

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

  • iterrows:行を変更しないでください

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

    代わりにDataFrame.apply()を使用してください:

    new_df = df.apply(lambda x: x * 2)
  • イタプル:

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

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


4
このスレッドを完了してから長い間このスレッドを読んでいる人からのちょっとした質問:df.apply()が効率の点でイタプルと比較してどうですか?
ラウルグアリーニ

4
注:for row in df[['c1','c2']].itertuples(index=True, name=None):行イテレータに特定の列のみを含めるように言うこともできます。
ブライアンバーンズ

12
の代わりにgetattr(row, "c1")、だけを使用できますrow.c1
viraptor

1
getattr(row, "c1")代わりにを使用するとrow.c1、のパフォーマンス上の利点が失われ、itertuples実際に文字列を介してプロパティにアクセスする必要がある場合は、代わりにiterrowsを使用する必要があると私は約90%確信しています。
夜間恐怖症

3
split-apply-combineがあることは知っていましたが、(質問のとおり)本当に DataFrame を反復処理する必要があったので、私はこの質問に出会いました。誰もがして改善するための贅沢を持っているnumbaし、cython(同じドキュメントは、「それは最初のPythonで、常に最適化する価値がある」と言います)。他のどの回答もこれらの警告に言及していないので、私は他の人が問題を回避する(時にはイライラする)のを助けるためにこの回答を書きました。誰かを誤解させたり、「それは正しいことだ」と言ったりすることは、私の意図ではありませんでした。答えを改善しました。
viddik13

201

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


12
これは、DataFrameを(.valuesを介して)numpy配列に変換し、配列を直接操作するよりも高速ですか?私は同じ問題を抱えていますが、最終的には派手な配列に変換してからcythonを使用することになりました。
vgoklani 2012年

12
@vgoklani行ごとの反復が非効率的で、オブジェクト以外のnumpy配列がある場合、特に多くの行を含む配列の場合、ほぼ確実にraw numpy配列を使用すると高速になります。絶対に必要な場合を除いて、行の反復を避ける必要があります
Phillip Cloud

7
私はdf.iterrows()、df.itertuples()、およびzip(df ['a']、df ['b'])の消費時間について少しテストし、別の回答に結果を投稿しました質問:stackoverflow.com/a/34311080/2142098
Richard Wong

154

ながら 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

5
2つの例の時間差の多くは、.iterrows()コマンドにラベルベースのインデックスを使用し、.itertuples()コマンドに整数ベースのインデックスを使用していることが原因であると思われます。
Alex

2
ファイナンスデータベースのデータフレーム(タイムスタンプ、4倍の浮動小数点)の場合、itertuplesは私のマシンでのiterrowsより19,57倍高速です。唯一のfor a,b,c in izip(df["a"],df["b"],df["c"]:ほぼ均等に高速です。
harbun

7
なぜそれが速いのか説明できますか?
安倍ミースラー2017年

4
@AbeMiessler iterrows()は、データの各行をシリーズにボックス化しますが、ボックス化itertuples()しません。
miradulo、2017

3
列の順序は実際には不確定であることに注意してください。これdfは、辞書から作成されるためrow[1]、任意の列を参照できるためです。実は、整数列と浮動小数点列の時間はほぼ同じです。
ブライアンバーンズ

88

あなたも使うことができます df.apply()して行を反復処理し、関数の複数の列にアクセスます。

docs: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']はデータフレームの列名を参照していますか?私はcsvファイルのいくつかの列からの一意の値で辞書を作成しようとしています。私はユニークなキーと値を持つ辞書を作成するためにあなたのロジックを使用してというエラーましTypeError例外を:(インデックス0'でu'occurred、「「シリーズのオブジェクトは、このように、彼らはハッシュ化することができない、変更可能です」)
SRS

コード: df ['Workclass'] = df.apply(lambda row:dic_update(row)、axis = 1)end of line id = 0 end of line def dic_update(row):if row not in dic:dic [row] = id id = id + 1
SRS 2015

気にしないで、私はそれを手に入れました。関数呼び出し行をdf_new = df ['Workclass']。apply(同じもの)に変更
SRS

2
軸のデフォルトを0にするのが最悪です
zthomas.nc '29

9
apply行を「反復」しないことに注意してください。むしろ、関数を行ごとに適用します。上記のコードは、あなたが本当にいる場合ではない仕事だろうやる異なる行全体に値を比較するとき、たとえば、必要性の反復とindecesを(その場合には、あなたは何もなく、繰り返し処理を行うことはできません)。
18

82

次のようにdf.iloc関数を使用できます。

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

1
iterrowsまたはitertuplesを優先してこれを回避する必要があることは知っていますが、その理由を知ることは興味深いでしょう。何かご意見は?
rocarvaj 2017年

12
これは、データ型を保持し、列を名前で参照する場合に知っている唯一の有効な手法です。 itertuplesデータ型は保持されますが、不要な名前は削除されます。 iterrows反対を行います。
ケンウィリアムズ

6
シンプルで表現力豊かな何かをするためにパンダのデータ構造の特異性を通り抜けようとするのに費やされた時間。これにより、コードが読みやすくなります。
ショーンアンダーソン

一方でfor i in range(df.shape[0])自分のアプリケーションのための上記ビットのアップこのアプローチを速める可能性がある、それはiterrowsより遅い3.5倍程度はまだだ()アプローチ。
Kim Miller

大規模なDatafrmes my_iter = df.itertuples()では、メモリの2倍とコピーに多くの時間がかかるため、これはより良いように見えます。も同じですiterrows()
バスティ

33

行と列を反復する方法を探していて、ここで終了しました:

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

18

実装する独自のイテレータを書くことができます 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)

これはに直接匹敵しpd.DataFrame.itertuplesます。同じタスクをより効率的に実行することを目指しています。


私の関数で指定されたデータフレームについて:

list(myiter(df))

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

またはpd.DataFrame.itertuples

list(df.itertuples(index=False))

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

包括的なテスト
すべての列を使用可能にし、列をサブセット化するテストを行います。

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);

ここに画像の説明を入力してください

ここに画像の説明を入力してください


2
コードを読みたくない人のために:青い線はintertuples、オレンジの線は、yieldブロックを介したイテレータのリストです。interrows比較されません。
ジェームズL.

18

効率的に反復する方法は?

pandasデータフレームを本当に反復する必要がある場合は、おそらくiterrows()の使用避けたいでしょう。さまざまな方法があり、通常の方法iterrows()が最善とはほど遠い。itertuples()は100倍高速にできます。

要するに:

  • 原則として、を使用してくださいdf.itertuples(name=None)。特に、固定数の列があり、255列未満の場合。ポイント(3)を参照
  • それdf.itertuples()以外の場合は、列にスペースや '-'などの特殊文字がある場合を除き、使用してください。ポイント(2)を参照
  • itertuples()最後の例を使用すると、データフレームに奇妙な列がある場合でも使用できます。ポイント(4)を参照
  • iterrows()以前のソリューションを使用できない場合にのみ使用してください。ポイント(1)を参照

パンダデータフレームの行を反復処理するさまざまな方法:

100万行、4列のランダムデータフレームを生成します。

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

1)通常iterrows()は便利ですが、すごく遅いです:

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)デフォルトitertuples()はすでに高速ですが、次のような列名では機能しませんMy Col-Name is very Strange(列が繰り返される場合、または列名を単純にpython変数名に変換できない場合は、このメソッドを回避する必要があります)。

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を使用するデフォルトはさらに高速ですが、列ごとに変数を定義する必要があるため、あまり便利ではありません。

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)最後に、named itertuples()は前のポイントよりも低速ですが、列ごとに変数を定義する必要はなく、などの列名で機能します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))

出力:

         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

この記事はiterrowsとitertuplesの非常に興味深い比較です


14

のすべての行をループするには、dataframe次を使用できます。

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

1
これは連鎖インデックスです。これはお勧めしません。
cs95

@ cs95代わりに何をお勧めしますか?
CONvid19

これを機能させる場合は、df.columns.get_locを呼び出して日付列の整数インデックス位置(ループ外)を取得し、内部で単一のilocインデックス呼び出しを使用します。
cs95

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

1
大規模なデータフレーム(数百万行など)で使用した場合のこのオプションのパフォーマンスはどうですか?
Bazyli Debowski

正直なところ、正確にはわかりませんが、どちらも「for」構造を使用しているため、最良の回答と比較して、経過時間はほぼ同じになると思います。ただし、メモリが異なる場合があります。
Grag2015年

4
これは連鎖インデックスです。これは使用しないでください。
cs95

7

時々役立つパターンは:

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

その結果:

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

6

ループへのすべての行dataframe利用各行の値が便利namedtuplesに変換することができるndarrayS。例えば:

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

行を繰り返す:

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

結果は:

[ 1.   0.1]
[ 2.   0.2]

の場合index=Trueインデックスはタプルの最初の要素として追加されます。これは、一部のアプリケーションでは望ましくない場合があります。


5

シリーズではなく、DataFrameを取得するときに、throw行を反復する方法があります。DataFrameとして返される行のリストとしてインデックスを渡すことができると言及している人はいないでしょう。

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

二重括弧の使用に注意してください。これは、単一行のDataFrameを返します。


これは、ソート後にデータフレームのn番目に大きい行を取得するのに非常に役立ちました。ありがとう!
Jason Harrison

3

値の表示と変更の両方に、を使用しますiterrows()。forループでタプルのアンパック(例を参照i, row)を使用しrowて、値を表示するためだけにforを使用iし、loc値を変更するときにメソッドで使用します。以前の回答で述べたように、ここでは、繰り返しているものを変更しないでください。

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

ここrowで、ループ内はその行のコピーであり、ビューではありません。したがって、row['A'] = 'New_Value'DataFrameを変更することはありません。ただし、DataFrameを使用ilocて指定し、作業を行うことができます。


2

応答パーティに遅れていることはわかっていますが、@ cs95の回答に追加したかっただけです。彼の回答では、パンダのベクトル化が、データフレームを使ってデータを計算する他のパンダの方法よりもはるかに優れていることを示しています。

最初にデータフレームを派手な配列に変換してからベクトル化を使用すると、pandasデータフレームのベクトル化よりも高速になります(データフレームシリーズに戻す時間も含まれます)。

次の関数を@ cs95のベンチマークコードに追加すると、これはかなり明白になります。

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]

ここに画像の説明を入力してください


1

また、numpyインデックスを作成してさらに高速化することもできます。これは実際には反復的ではありませんが、特定のアプリケーションでは反復よりもはるかにうまく機能します。

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

また、配列にキャストすることもできます。これらのインデックス/選択はすでにNumpy配列のように動作するはずですが、問題が発生し、キャストする必要がありました

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

1

パンダのデータフレームの行を反復する方法はたくさんあります。非常にシンプルで直感的な方法の1つは次のとおりです。

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

この例では、ilocを使用してデータフレームの各桁を分離しています。

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

一部のライブラリ(たとえば、私が使用するJava相互運用ライブラリ)では、データをストリーミングする場合など、値を一度に1行ずつ渡す必要があります。ストリーミングの性質を再現するために、データフレーム値を1つずつ「ストリーミング」します。以下のように記述しました。これは時々役に立ちます。

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

使用できるもの:

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

また、反復される行の値/名前のマッピングを保持します。上記のように、applyやCythonを使用するよりも明らかに遅いですが、状況によっては必要です。


0

要するに

  • 可能であればベクトル化を使用する
  • 操作をベクトル化できない場合-リスト内包表記を使用
  • 行全体を表す単一のオブジェクトが必要な場合-itertuplesを使用します
  • 上記が遅すぎる場合-swifter.applyを試してください
  • それでも遅すぎる場合-Cythonルーチンを試してください

詳細 このビデオの

基準 pandas DataFrameの行に対する反復のベンチマーク

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.