note.nkmk.me

pandas.DataFrameのforループ処理(イテレーション)

Date: 2017-12-08 / Modified: 2018-07-08 / tags: Python, pandas
このエントリーをはてなブックマークに追加

pandas.DataFrameをfor文でループ処理(イテレーション)する場合、単純にそのままfor文で回すと列名が返ってくるだけなので、繰り返し処理のためのメソッドを使って列ごと・行ごと(一列ずつ・一行ずつ)の値を取得する。

以下のpandas.DataFrameを例とする。

import pandas as pd

df = pd.DataFrame({'age': [24, 42], 'state': ['NY', 'CA'], 'point': [64, 92]},
                  index=['Alice', 'Bob'])

print(df)
#        age state  point
# Alice   24    NY     64
# Bob     42    CA     92

以下の内容について説明する。

  • pandas.DataFrameをそのままforループに適用
  • 1列ずつ取り出す
    • DataFrame.iteritems()メソッド
  • 1行ずつ取り出す
    • DataFrame.iterrows()メソッド
    • DataFrame.itertuples()メソッド
  • 特定の列の値を順に取り出す
  • ループ処理で値を更新する

for文についての詳細は以下の記事を参照。

スポンサーリンク

pandas.DataFrameをそのままforループに適用

pandas.DataFrameをそのままforループにつっこんだ場合は以下のようにコラム名(列名)が順に取り出される。

for column_name in df:
    print(type(column_name))
    print(column_name)
    print('======\n')
# <class 'str'>
# age
# ======
# 
# <class 'str'>
# state
# ======
# 
# <class 'str'>
# point
# ======
# 

特殊メソッド__iter__()が呼ばれている。

for column_name in df.__iter__():
    print(type(column_name))
    print(column_name)
    print('======\n')
# <class 'str'>
# age
# ======
# 
# <class 'str'>
# state
# ======
# 
# <class 'str'>
# point
# ======
# 

1列ずつ取り出す

DataFrame.iteritems()メソッド

iteritems()メソッドを使うと、1列ずつコラム名(列名)とその列のデータ(pandas.Series型)のタプル(column name, Series)を取得できる。

pandas.Seriesはインデックス名などを指定してその行の値を取り出せる。

for column_name, item in df.iteritems():
    print(type(column_name))
    print(column_name)
    print('~~~~~~')

    print(type(item))
    print(item)
    print('------')

    print(item['Alice'])
    print(item[0])
    print(item.Alice)
    print('======\n')
# <class 'str'>
# age
# ~~~~~~
# <class 'pandas.core.series.Series'>
# Alice    24
# Bob      42
# Name: age, dtype: int64
# ------
# 24
# 24
# 24
# ======
# 
# <class 'str'>
# state
# ~~~~~~
# <class 'pandas.core.series.Series'>
# Alice    NY
# Bob      CA
# Name: state, dtype: object
# ------
# NY
# NY
# NY
# ======
# 
# <class 'str'>
# point
# ~~~~~~
# <class 'pandas.core.series.Series'>
# Alice    64
# Bob      92
# Name: point, dtype: int64
# ------
# 64
# 64
# 64
# ======
# 

1行ずつ取り出す

DataFrame.iterrows()メソッド

iterrows()メソッドを使うと、1行ずつ、インデックス名(行名)とその行のデータ(pandas.Series型)のタプル(index, Series)を取得できる。

pandas.Seriesはコラム名などを指定してその列の値を取り出せる。

for index, row in df.iterrows():
    print(type(index))
    print(index)
    print('~~~~~~')

    print(type(row))
    print(row)
    print('------')

    print(row['point'])
    print(row[2])
    print(row.point)
    print('======\n')
# <class 'str'>
# Alice
# ~~~~~~
# <class 'pandas.core.series.Series'>
# age      24
# state    NY
# point    64
# Name: Alice, dtype: object
# ------
# 64
# 64
# 64
# ======
# 
# <class 'str'>
# Bob
# ~~~~~~
# <class 'pandas.core.series.Series'>
# age      42
# state    CA
# point    92
# Name: Bob, dtype: object
# ------
# 92
# 92
# 92
# ======
# 

DataFrame.itertuples()メソッド

itertuples()メソッドを使うと、1行ずつ、インデックス名(行名)とその行のデータのタプルを取得できる。タプルの最初の要素がインデックス名となる。

デフォルトではPandasという名前のnamedtupleを返す。namedtupleなので、[]のほか.でも各要素の値にアクセスできる。

for row in df.itertuples():
    print(type(row))
    print(row)
    print('------')

    print(row[3])
    print(row.point)
    print('======\n')
# <class 'pandas.core.frame.Pandas'>
# Pandas(Index='Alice', age=24, state='NY', point=64)
# ------
# 64
# 64
# ======
# 
# <class 'pandas.core.frame.Pandas'>
# Pandas(Index='Bob', age=42, state='CA', point=92)
# ------
# 92
# 92
# ======
# 

引数nameNoneとするとノーマルのタプルを返す。

for row in df.itertuples(name=None):
    print(type(row))
    print(row)
    print('------')

    print(row[3])
    print('======\n')
# <class 'tuple'>
# ('Alice', 24, 'NY', 64)
# ------
# 64
# ======
# 
# <class 'tuple'>
# ('Bob', 42, 'CA', 92)
# ------
# 92
# ======
# 

特定の列の値を順に取り出す

上述のiterrows(), itertuples()メソッドは各行のすべての列の要素が取り出せるが、特定の列の要素のみが必要な場合は以下のようにも書ける。

pandas.DataFrameの列はpandas.Seriesとなる。

print(df['age'])
# Alice    24
# Bob      42
# Name: age, dtype: int64

print(type(df['age']))
# <class 'pandas.core.series.Series'>

pandas.Seriesをforループに適用するとその値が順に取得できるので、pandas.DataFrameの列を指定してforループに適用するとその列の値が順に取得できる。

for age in df['age']:
    print(age)
# 24
# 42

組み込み関数zip()を使えば複数列の値をまとめて取得することも可能。

for age, point in zip(df['age'], df['point']):
    print(age)
    print(point)
    print('======\n')
# 24
# 64
# ======
# 
# 42
# 92
# ======
# 

インデックス(行名)を取得したい場合はindex属性を使う。

print(df.index)
# Index(['Alice', 'Bob'], dtype='object')

print(type(df.index))
# <class 'pandas.core.indexes.base.Index'>

for index in df.index:
    print(index)
# Alice
# Bob

ループ処理で値を更新する

1行ずつ値を取り出すiterrows()メソッドはビューではなくコピーを返すので、pandas.Seriesを変更しても元データは更新されない。

for index, row in df.iterrows():
    row.point += 5

print(df)
#        age state  point
# Alice   24    NY     64
# Bob     42    CA     92

atで元のDataFrameからデータを選択して処理すると更新される。

for index, row in df.iterrows():
    df.at[index, 'point'] += 5

print(df)
#        age state  point
# Alice   24    NY     69
# Bob     42    CA     97

atについては以下の記事も参照。

なお、上の例のような単純な処理であればforループを使う必要はなく、以下のように書ける。こちらのほうが速い。

上で更新したオブジェクトをさらに更新している。

df['point'] += 5

print(df)
#        age state  point
# Alice   24    NY     74
# Bob     42    CA    102
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事