pandas

【pandas】DataFrameのデータ選択方法

【pandas】DataFrameのデータ選択方法 loc iloc at iat

pandasのDataFrameのデータ選択方法について解説します。

DataFrameのデータ選択方法

pandasを利用する際にとても重要になってくるのがDataFrameの扱いです。本記事ではDataFrameから必要なデータを選択する方法の基本について説明します。

DataFrameのデータ選択方法として是非覚えておいて欲しいのは後述するlocメソッドやilocメソッドですが、locやilocを使用しないデータアクセス方法も色々とあります。

以降ではよくDataFrameのデータ選択で出てくる利用ケースを想定していくつかのパターンで基本的なデータ選択方法について説明していきます。

列名を指定して特定の列を取得する方法

基本的な使用方法

DataFrameで、列名を指定して特定の列を取得する場合には以下のように使用します。

import pandas as pd

attr1 = pd.Series([10, 20, 30, 40, 50], index=['A', 'B', 'C', 'D', 'E'])
attr2 = pd.Series([60, 70, 80, 90, 100], index=['A', 'B', 'C', 'D', 'E'])
df = pd.DataFrame({'attr1': attr1, 'attr2': attr2})
print(df, '\n')

# 列名を指定して特定の列情報を取得する(辞書のようにアクセス)
print(df['attr1'], '\n')
# 列名を変数のようにして読み込むことも可能
print(df.attr1)
【実行結果】
   attr1  attr2
A     10     60
B     20     70
C     30     80
D     40     90
E     50    100 

A    10
B    20
C    30
D    40
E    50
Name: attr1, dtype: int64 

A    10
B    20
C    30
D    40
E    50
Name: attr1, dtype: int64

使い方は、Python辞書のキーを指定してアクセスする方法と同様でdf[‘列名’]とすることで特定列を取得できます。また、列名を変数名のように「df.列名」としてアクセスすることも可能です。

注意事項:列名とメソッド名の重複に注意

列名を変数名のように「df.列名」としてアクセスする場合には注意事項があります。DataFrameのメソッドと列名重複してしまうと取得できるデータは想定のものにならないため注意しましょう。

import pandas as pd

attr1 = pd.Series([10, 20, 30, 40, 50], index=['A', 'B', 'C', 'D', 'E'])
attr2 = pd.Series([60, 70, 80, 90, 100], index=['A', 'B', 'C', 'D', 'E'])
df = pd.DataFrame({'attr1': attr1, 'pop': attr2})
print(df, '\n')

# メソッド名と重なる場合、辞書形式の取得と属性名での取得は一致しない
print(f'df.pop: \n{df.pop}\n')
print(f"df['pop']: \n{df['pop']}\n")
print(df.pop is df['pop'])
【実行結果】
   attr1  pop
A     10   60
B     20   70
C     30   80
D     40   90
E     50  100 

df.pop: 
<bound method DataFrame.pop of    attr1  pop
A     10   60
B     20   70
C     30   80
D     40   90
E     50  100>

df['pop']: 
A     60
B     70
C     80
D     90
E    100
Name: pop, dtype: int64

False

上記例では、データが「pop」という列を持っています。しかし、DataFrameのメソッドにpopがあるため、df.popとして取得できるものはdf[‘pop’]として取得できるものとは異なります。(isでも確認を取っています)

このように、DataFrameのメソッドと列名が重複していると想定外の結果となることもあるので注意して使用するようにしてください。

特定の列情報を任意順序に並べたデータを取得する方法

DataFrameの列の順序を任意に並べ替えたい場合には、以下のように列名を並べて取得します。

import pandas as pd

attr1 = pd.Series([10, 20, 30, 40, 50], index=['A', 'B', 'C', 'D', 'E'])
attr2 = pd.Series([60, 70, 80, 90, 100], index=['A', 'B', 'C', 'D', 'E'])
df = pd.DataFrame({'attr1': attr1, 'attr2': attr2})
print(df, '\n')

# 特定の列名を指定し、任意順序で並べ替えてデータを取得する(同じ列の複製も可能)
print(df[['attr2', 'attr1', 'attr1', 'attr2']])
【実行結果】
   attr1  attr2
A     10     60
B     20     70
C     30     80
D     40     90
E     50    100 

   attr2  attr1  attr1  attr2
A     60     10     10     60
B     70     20     20     70
C     80     30     30     80
D     90     40     40     90
E    100     50     50    100

上記例では、列の順序を表すようなリストを[]の中に渡すことで、指定した列順序で並び替えています。また、attr1, attr2を複数回指定していますが、列が複製されていることが分かるかと思います。このように、同一の列名を複数回リストに指定すれば、列データを複製するようなことも可能になります。

既存の列を用いて計算した結果列を作成する方法

DataFrameの既存の列を用いて計算した結果で新しい列を作成したくなる場合があります。その際には、既存列を用いて以下のようにすることができます。

import pandas as pd

attr1 = pd.Series([10, 20, 30, 40, 50], index=['A', 'B', 'C', 'D', 'E'])
attr2 = pd.Series([60, 70, 80, 90, 100], index=['A', 'B', 'C', 'D', 'E'])
df = pd.DataFrame({'attr1': attr1, 'attr2': attr2})
print(df, '\n')

# 既存の列から計算して新しい列を作成する
df['sum'] = df['attr1'] + df['attr2']
print(df)
【実行結果】
   attr1  attr2
A     10     60
B     20     70
C     30     80
D     40     90
E     50    100 

   attr1  attr2  sum
A     10     60   70
B     20     70   90
C     30     80  110
D     40     90  130
E     50    100  150

df[‘sum’]は元々のデータには存在していないわけですが、上記例のように足し算の計算式を指定することで新しい’sum’という列を作成することができます。上記例は、足し算「+」ですが、その他の演算や関数等を使って新しい列を作ることももちろん可能です。

スライスで特定のキーを持つ行を選択する方法

DataFrameの特定のキーを持つ行を選択する場合にはスライスが使用できます。

import pandas as pd

attr1 = pd.Series([10, 20, 30, 40, 50], index=['A', 'B', 'C', 'D', 'E'])
attr2 = pd.Series([60, 70, 80, 90, 100], index=['A', 'B', 'C', 'D', 'E'])
df = pd.DataFrame({'attr1': attr1, 'attr2': attr2})
print(df, '\n')

# ===== スライスで特定のキーを持つ行を選択する
# 明示的なインデックスを使用する場合
print(df['B':'D'], '\n')
# 暗黙的なインデックスを使用する場合
print(df[1:3])
【実行結果】
   attr1  attr2
A     10     60
B     20     70
C     30     80
D     40     90
E     50    100 

   attr1  attr2
B     20     70
C     30     80
D     40     90 

   attr1  attr2
B     20     70
C     30     80

[]の中にキーとなるインデックスをスライスで指定すると該当する行を選択できます。pandasのDataFrameやSeriesでは、インデックスには明示的なインデックスと暗黙的なインデックスがあります。

明示的なインデックスは「index=」で指定しているインデックスです。一方、暗黙的なインデックスは表面上は見えていませんが0~の数値で振られているインデックスです。例えば上記の例でいえば、明示的なインデックス「’A’」に相当する暗黙的なインデックスは「0」となります。

注意が必要なのは、明示的なインデックスのスライスでは終わりを含みますが、暗黙的なインデックスのスライスでは終わりを含まないことです。上記例でいうと、[‘B’:’D’]という指定であれば’D’に該当する行を含みますが、[1:3]とすると3に該当する行は含まれません。

マスキングで特定条件に一致する行を選択する方法

DataFrameの中から特定条件に一致する行を選択するには、以下の例のようにマスキングすることができます。

import pandas as pd

attr1 = pd.Series([10, 20, 30, 40, 50], index=['A', 'B', 'C', 'D', 'E'])
attr2 = pd.Series([60, 70, 80, 90, 100], index=['A', 'B', 'C', 'D', 'E'])
df = pd.DataFrame({'attr1': attr1, 'attr2': attr2})
print(df, '\n')

# 特定の条件に一致する行を選択する
print(df[(df['attr1'] > 10) & (df['attr2'] < 100)])
【実行結果】
   attr1  attr2
A     10     60
B     20     70
C     30     80
D     40     90
E     50    100 

   attr1  attr2
B     20     70
C     30     80
D     40     90

上記例では「attr1列の値が10より大きい」かつ「attr2列の値が100より小さい」に該当する行が選択されます。df[‘attr1’] > 10といった部分は該当する行がTrueとなるようなbool型になります。df[‘attr2’] < 100についても同様です。

選択対象とする行がTrueとなるbool値をDataFrameの[]内に指定することで該当する行だけマスキングすることができます。

任意の行、列の値を選択する方法 ~loc, iloc, at, iat~

DataFrameで任意の行、列の値を選択する方法としては、loc, iloc, at, iatを使用することができます。これらのメソッドの使い方は是非覚えましょう。

pandasのDataFrameやSeriesでは、インデックスには明示的なインデックスと暗黙的なインデックスがあります。明示的なインデックスは「index=」等で指定しているインデックスで、一方の暗黙的なインデックスは表面上は見えていませんが0~の数値で振られているインデックスです。

以降で説明するloc, iloc, at, iatに関して「i」がついているものは暗黙的なインデックスを対象に、「i」がついていないものは明示的なインデックスを対象にしてデータ選択するメソッドであると理解してください。

特定位置の情報を選択する方法

DataFrameにおける特定位置の値(例えば「2行1列の値」等)を選択する場合は、loc, iloc, at, iatを使用して以下の例のようにデータを選択ができます。

import pandas as pd

attr1 = pd.Series([10, 20, 30, 40, 50], index=['A', 'B', 'C', 'D', 'E'])
attr2 = pd.Series([60, 70, 80, 90, 100], index=['A', 'B', 'C', 'D', 'E'])
attr3 = pd.Series([110, 120, 130, 140, 150], index=['A', 'B', 'C', 'D', 'E'])
df = pd.DataFrame({'attr1': attr1, 'attr2': attr2, 'attr3': attr3})
print(df, '\n')

# 特定の位置を選択する
# 明示的なインデックスを使用する場合
print(df.loc['C', 'attr2'], '\n')
# atを使っても同様のことができる
print(df.at['C', 'attr2'], '\n')

# 暗黙的なインデックスを使用する場合
print(df.iloc[2, 1], '\n')
# iatを使っても同様のことができる
print(df.iat[2, 1])
【実行結果】
   attr1  attr2  attr3
A     10     60    110
B     20     70    120
C     30     80    130
D     40     90    140
E     50    100    150 

80 

80 

80 

80

上記例のように[]内に、[行のインデックス, 列のインデックス]という形で指定することで該当する特定位置の値を取得することができます。

locやatは明示的なインデックスを対象にし、ilocやiatは暗黙的なインデックスを対象にします。特定位置の値を選択する場合には、locとat、ilocとiatについては結果は同じです。locやilocは以降で説明するようなスライスでのデータ選択にも対応しているという点で異なります。

スライスで任意の行、列を選択する方法

DataFrameにおける任意の行、列をスライスで選択する場合は、loc, ilocを使用して以下例のようにデータ選択ができます。

import pandas as pd

attr1 = pd.Series([10, 20, 30, 40, 50], index=['A', 'B', 'C', 'D', 'E'])
attr2 = pd.Series([60, 70, 80, 90, 100], index=['A', 'B', 'C', 'D', 'E'])
attr3 = pd.Series([110, 120, 130, 140, 150], index=['A', 'B', 'C', 'D', 'E'])
df = pd.DataFrame({'attr1': attr1, 'attr2': attr2, 'attr3': attr3})
print(df, '\n')

# 任意の行、列を選択する(スライスを使用する例)
# 明示的なインデックスを使用する場合
print(df.loc['B':'D', 'attr2':'attr3'], '\n')
# 暗黙的なインデックスを使用する場合
print(df.iloc[1:3, 1:2])
【実行結果】
   attr1  attr2  attr3
A     10     60    110
B     20     70    120
C     30     80    130
D     40     90    140
E     50    100    150 

   attr2  attr3
B     70    120
C     80    130
D     90    140 

   attr2
B     70
C     80

上記例のように[]内に、[行のスライス, 列のスライス]という形で指定することで、指定した行の範囲、列の範囲に該当するデータを選択することができます。

ここで注意が必要なのは、明示的なインデックスでは終わりを含みますが、暗黙的なインデックスでは終わりを含まないことです。上記例の行スライスでいうと、例えば「’B’:’D’」という指定であれば「’D’」は含みますが、「1:3」とすると3は含まれません。列スライスについても同様です。