【Pandas効率化】DataFrameでforループ処理!iterrows, itertuples, itemsを使いこなそう


 

PandasのDataFrameでデータ処理を行う際、「各行や各列に対して何らかの操作を行いたい」という場面はよくあります。Pythonの基本的な**forループ**(イテレーション)は、このような繰り返し処理に非常に便利です。しかし、PandasのDataFrameは大規模なデータを扱うことが多いため、効率的なループ処理の方法を知っておくことが重要です。この記事では、DataFrameでforループを効果的に使うための主要なイテレーションメソッド、iterrows()itertuples()items()を、短いサンプルコードと丁寧な解説でご紹介します。


 

DataFrameでforループ処理を行う理由

 

Pandasでは、特定の操作に対してはapply()やベクトル化された演算(SeriesやDataFrame全体への演算)を使う方が一般的に高速で推奨されます。しかし、以下のような場合にはforループ処理が役立ちます。

  • 複雑な行ごとのロジック: 各行の値に基づいて、その行に固有の複雑な条件分岐や計算を行う場合。

  • 特定の列へのアクセス: 特定の列名やインデックスを使って、その列のデータに順番にアクセスしたい場合。

  • デバッグや確認: 大規模なデータセットの一部をサンプリングして、手動で処理の流れを確認したい場合。


 

iterrows()で各行を反復処理する

 

iterrows()は、DataFrameの各行を反復処理するためのメソッドです。各イテレーションで、行のインデックスSeries形式の行データを返します。

Python
 
import pandas as pd

# サンプルDataFrameの作成
df = pd.DataFrame({
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Age': [25, 30, 35],
    'City': ['Tokyo', 'Osaka', 'Nagoya']
})
print("オリジナルDataFrame:\n", df)

print("\n--- iterrows()で各行を処理 ---")
for index, row in df.iterrows():
    print(f"インデックス: {index}")
    print(f"名前: {row['Name']}, 年齢: {row['Age']}, 都市: {row['City']}")

解説:

  • for index, row in df.iterrows(): とすることで、ループごとにindexに現在の行のインデックスが、rowにその行のデータがSeriesとして代入されます。

  • row['Name']のように、列名を指定して各列の値にアクセスできます。

注意点:

  • iterrows()は行をSeriesとして返すため、データ型が変換されることがあります(例: 整数列が浮動小数点数になる)。

  • パフォーマンスはitertuples()よりも劣る場合があります。


 

itertuples()で各行を効率的に反復処理する

 

itertuples()は、iterrows()よりも高速に各行を反復処理したい場合に推奨されます。各イテレーションで、行の**名前付きタプル(namedtuple)**を返します。

Python
 
print("\n--- itertuples()で各行を処理 ---")
for row_tuple in df.itertuples():
    print(f"インデックス: {row_tuple.Index}")
    print(f"名前: {row_tuple.Name}, 年齢: {row_tuple.Age}, 都市: {row_tuple.City}")

解説:

  • row_tupleは名前付きタプルなので、row_tuple.Nameのように属性アクセスで各列の値にアクセスできます。インデックスはrow_tuple.Indexで取得できます。

  • タプルであるため、Seriesよりもデータ型変換が少なく、一般的に**iterrows()よりも高速**です。大規模なDataFrameを処理する場合におすすめです。


 

items()で各列を反復処理する

 

DataFrameの各列を反復処理したい場合は、items()メソッドが便利です。各イテレーションで、列の名前(列名)とSeries形式の列データを返します。

Python
 
print("\n--- items()で各列を処理 ---")
for col_name, col_data in df.items():
    print(f"列名: {col_name}")
    print(f"列データ:\n{col_data}")
    print("-" * 20)

解説:

  • for col_name, col_data in df.items(): とすることで、ループごとにcol_nameに現在の列名が、col_dataにその列のデータがSeriesとして代入されます。

  • 特定の列に対して集計や変換を行いたい場合に非常に役立ちます。


 

どのイテレーションメソッドを選ぶべきか?使い分けのポイント

 

メソッド 適用対象 返される形式 主な用途 パフォーマンス
iterrows() DataFrameの各行 (index, Series) 各行のデータをSeriesとして扱いたい場合、可読性重視
itertuples() DataFrameの各行 (index, namedtuple) 各行のデータを高速に処理したい場合、大規模データ向け
items() DataFrameの各列 (column_name, Series) 各列のデータ(Series)に対して処理を行いたい場合

💡 最適な選択のヒント:

  • 行ごとに高速な処理を行いたいなら itertuples()

  • 行データをSeriesとして扱いたい場合や、インデックスも合わせて確認したい場合は iterrows()

  • 列ごとに処理を行いたいなら items()

重要な注意点:

Pandasの処理で最も効率的なのは、可能な限りベクトル化された演算(例: df[‘A’] * 2)や組み込みメソッド(例: df.sum(), df.fillna())を利用することです。これらは内部的にC言語で最適化されており、Pythonのループよりもはるかに高速です。apply()もループよりは高速ですが、究極的にはベクトル化が最速です。

これらのイテレーションメソッドは、ベクトル化が難しいような複雑なロジックや、特定のデバッグ、または学習目的で利用することを検討してください。


 

まとめ

 

Pandas DataFrameでforループ処理を行う際には、目的に応じてiterrows()itertuples()items()を適切に使い分けることが重要です。行ごとの高速処理にはitertuples()、列ごとの処理にはitems()、そして汎用的な行処理にはiterrows()が適しています。しかし、パフォーマンスが最優先される場合は、常にベクトル化されたPandasの機能やapply()メソッドの活用を検討してください。これらの知識を活かして、あなたのデータ分析ワークフローをさらに効率化しましょう!