[pandas] インデクス属性

[pandas] インデクス属性

インデクス属性

 Series や DataFrame には、要素を抽出するためのインデクス属性 (loc, iloc, at, iat) が備えられています。

loc, iloc

 Series や DataFrame の要素の参照方法は、時としてユーザーを混乱させることがあります。たとえば、次のように偶数ラベルを付した Seriesオブジェクトを生成したとします。

# PANDAS_SERIES_LOC-1

# Seriesオブジェクトを生成
data = pd.Series(["apple", "orange", "banana", "grape", "strawberry"],
                 index = {2, 4, 6, 8, 10})

 data[2] によるアクセスはラベル 2 にマップされた要素 "apple" を取得します (ディクショナリでいえばキー 2 に対応する値 "apple" を取り出すことに対応します)。

# PANDAS_SERIES_LOC-2

print(data[2])
apple

 しかし、data[1] と記述すると、1 というキーは存在しないので KeyError を発生します。

# PANDAS_SERIES_LOC-3

print(data[1])
KeyError: 1

 そうすると、data[1:3] のようなスライス表記もエラーを返しそうですが、実際には予想に反して 2 番目と 3 番目の要素を抽出します。

# PANDAS_SERIES_LOC-4

print(data[1:3])
4    orange
6    banana
dtype: object

 スライス表記は一般的な Python や NumPy と同じく、各要素に連番 0, 1, 2, 3, ... を割り当てる方式でアクセスするからです。このようなスタイル混合は様々なミスを引き起こす要因となるので、アクセスのスタイルを明確にするために、lociloc という属性が用意されています。

 loc属性はラベルを介して要素にアクセスします:

# PANDAS_SERIES_LOC-5

# ラベルを使ってスライス
print(data.loc[2:5])
2     apple
4    orange
dtype: object

 iloc属性は従来の Python スタイルにしたがって要素にアクセスします:

# PANDAS_SERIES_LOC-6

# 従来のPython方式でスライス
print(data.iloc[2:5])
6         banana
8          grape
10    strawberry
dtype: object

 DataFrame における loc と iloc 属性の使い方も確認しておきましょう。
 次のコードで東北地方の面積と人口の表を作成します (Wikipedia から抜粋した 2015年の国勢調査にもとづくデータです)。

# PANDAS_DATAFRAME_LOC-1

# 東北地方の県別面積一覧(平方キロメートル)
area = pd.Series({"岩手":15275,
                  "福島":13784,
                  "秋田":11638,
                  "青森":9646,
                  "山形":9323,
                  "宮城":7282})

# 東北地方の県別人口一覧(人)
pop = pd.Series({"岩手":1279594,
                 "福島":1914039,
                 "秋田":1023119,
                 "青森":1308265,
                 "山形":1123891,
                 "宮城":2333899})

# 列ラベルの割り当て
columns = {"面積":area, "人口":pop}

# DataFrameを作成
data = pd.DataFrame(columns)

print(data)
       面積       人口
岩手  15275  1279594
福島  13784  1914039
秋田  11638  1023119
青森   9646  1308265
山形   9323  1123891
宮城   7282  2333899

 DataFrame の loc属性は行ラベルと列ラベルを使ってデータにアクセスします。たとえば、秋田県の人口を参照したいときは次のように記述します。

# PANDAS_DATAFRAME_LOC-2

# 秋田県の人口密度を取得
print(data.loc["秋田", "人口"])
1023119

 山形県の面積を取得する場合は次のように記述します。

# PANDAS_DATAFRAME_LOC-3

# 山形県の面積を取得
print(data.loc["山形", "面積"])
9323

 スライスを使って複数項目を参照することもできます。

# PANDAS_DATAFRAME_LOC-4

# 福島、秋田、青森の面積と人口を取得
print(data.loc["福島":"青森"])
       面積       人口
福島  13784  1914039
秋田  11638  1023119
青森   9646  1308265

 実行結果を見てわかるように、ラベルによるスライスは NumPy 配列のインデックスによるスライスとは異なり、指定ラベルに対応する要素をすべて返します。

 コロン (:) を使って行や列を参照することもできます。
 たとえば、面積一覧が欲しい場合は次のように記述します。

# PANDAS_DATAFRAME_LOC-5

# 東北地方の面積一覧を取得
print(data.loc[:, "面積"])
岩手    15275
福島    13784
秋田    11638
青森     9646
山形     9323
宮城     7282
Name: 面積, dtype: int64

 DataFrame の iloc属性は行と列に割り振られた連番 (暗黙的インデクス) を使ってデータにアクセスします。つまり NumPy の二次元配列と同じアクセススタイルとなります。たとえば、秋田県の人口密度にアクセスする場合は以下のように記述します。

# PANDAS_DATAFRAME_LOC-6

# 秋田県の人口密度を取得
print(data.iloc[2, 0])
11638

 ある行や列を参照したい場合なども、NumPy のアクセス方式に準じます。たとえば、青森県の面積と人口密度にアクセスしたい場合は data.iloc[3, :] と記述します。

# PANDAS_DATAFRAME_LOC-7

# 秋田県の面積と人口密度を取得
print(data.iloc[3, :])
面積       9646
人口    1308265
Name: 青森, dtype: int64

 このとき、コードPD_16-7 の実行結果にあるように、参照した行のラベルも Name として表示されます。
 

at, iat

 atiat は1つの要素しか参照できないという点を除いて、それぞれ loc, iloc と同じはたらきをします。loc, iloc があれば事足りるので、at, iat を積極的に使用する利点は特にありませんが、一応以下に使用例を載せておきます。最初に四国の各県の面積と人口の表を作成しておきます。

# PANDAS_AT-1

# 四国の県別面積一覧(平方キロメートル)
area = pd.Series({"徳島":4147,
                  "香川":1877,
                  "愛媛":5676,
                  "高知":7104})

# 四国の県別人口一覧(人)
pop = pd.Series({"徳島":755733,
                 "香川":976263,
                 "愛媛":1385262,
                 "高知":728276})

# 列ラベルの割り当て
columns = {"面積":area, "人口":pop}

# DataFrameを作成
data = pd.DataFrame(columns)

print(data)
      面積       人口
徳島  4147   755733
香川  1877   976263
愛媛  5676  1385262
高知  7104   728276

 at を使って愛媛県の面積にアクセスしてみます。

# PANDAS_AT-2

# 愛媛県の面積を取得
print(data.at["愛媛", "面積"])
5676

 iat は 0 から始まる連番ラベルでアクセスします。
 たとえば、香川県の人口を参照する場合は次のように記述します。

# PANDAS_AT-3

# 香川県の人口を取得
print(data.iat[1, 1])
976263