pandas

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

【pandas】Seriesのデータ選択方法 loc iloc

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

Seriesデータの選択方法

pandasのSeriesのデータ選択方法には、以下のようにいくつかの種類があります。

  • Pythonの辞書と同様のデータ選択方法
  • NumPy配列と同様のデータ選択方法
  • pandasのデータ選択方法(locメソッド、ilocメソッド)

Seriesは、Pythonの辞書の特殊版のようなものであるため、辞書と同じようにデータアクセスができ、同様のメソッドを使用することができます。また、NumPyの配列(ndarray)と同様なデータ選択(スライス、マスキング、ファンシーインデックス)も可能です。

また、pandas特有のデータアクセス方法としては、locメソッドやilocメソッドがあります。通常のスライスでのアクセスには少し複雑な点があるため、loc/ilocの使用方法はしっかり覚えておくとよいでしょう。

以降でそれぞれ例を用いて説明をしていきます。

Pythonの辞書と同様のデータ選択方法

pandasのSeriesは、Pythonの辞書と同様にデータへアクセスでき、辞書と同様の各種メソッドを使用することができます。

インデックスで要素を指定して選択

シンプルな要素へのアクセス方法は、インデックスで要素を指定してデータ選択する方法です。

import pandas as pd

data = pd.Series([1, 2, 3, 4, 5], index=["a", "b", "c", "d", "e"])
print(data, "\n")

# 要素をインデックスで指定して参照
print(data["b"])
【実行結果】
a    1
b    2
c    3
d    4
e    5
dtype: int64 

2

Pythonの辞書でキーを指定してアクセスすることと同様に、[]内にインデックスを指定することでデータを参照できます。

要素の値を上書きする

Seriesの要素の値を上書きする場合は、インデックスでアクセスした要素に値を代入することで上書きが可能です。

import pandas as pd

data = pd.Series([1, 2, 3, 4, 5], index=["a", "b", "c", "d", "e"])
print(data, "\n")

# 値を上書きする
data["e"] = 10
print(data)
【実行結果】
a    1
b    2
c    3
d    4
e    5
dtype: int64 

a     1
b     2
c     3
d     4
e    10
dtype: int64

インデックス情報を取得する ~keys~

Seriesのインデックス情報は、インデックスオブジェクトに格納されています。インデックス情報は以下のようにkeysメソッドを使用することで取得できます。

import pandas as pd

data = pd.Series([1, 2, 3, 4, 5], index=["a", "b", "c", "d", "e"])
print(data, "\n")

# インデックスを取り出す
print(data.keys())
【実行結果】
a    1
b    2
c    3
d    4
e    5
dtype: int64 

Index(['a', 'b', 'c', 'd', 'e'], dtype='object')

結果を見るとIndexオブジェクトが返ってきていることが分かります。pandasにおけるIndexの基本は「Indexの基本」で紹介しているので興味があれば参考にしてください。

要素を取得してリストや辞書に変換する ~items~

Seriesのデータから要素を取得してPythonのリストや辞書で処理する場合には、以下のようにitemsメソッドを使用します。

import pandas as pd

data = pd.Series([1, 2, 3, 4, 5], index=["a", "b", "c", "d", "e"])
print(data, "\n")

# 要素を取得して、リストや辞書に変換する
print(f"data.items(): {data.items()}")
print(f"list(data.items()): {list(data.items())}")
print(f"dict(data.items()): {dict(data.items())}", "\n")

# itemsはfor文で使用可能
print("for文で各値を取得")
for idx, val in data.items():
    print(idx, val)
【実行結果】
a    1
b    2
c    3
d    4
e    5
dtype: int64 

data.items(): <zip object at 0x0000029C73F0F580>
list(data.items()): [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
dict(data.items()): {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5} 

for文で各値を取得
a 1
b 2
c 3
d 4
e 5

上記のようにdata.items()により、Seriesのデータ要素を取得できます。zip objectは上記例のようにlistdictに渡すことでリストや辞書に変換ができます。

また、zip objectはイテラブルなため、for文を使って繰り返し要素を取り出して処理をすることが可能です。zipを用いてfor文でデータを取り出す基本的な方法は「zipを用いたfor文の使い方」にまとめていますので興味があれば参考にしてください。

インデックス(キー)の有無を確認する ~in, not in~

Seriesのインデックス(キー)が存在するかどうかを確認するにはinnot inで確認ができます。

import pandas as pd

data = pd.Series([1, 2, 3, 4, 5], index=["a", "b", "c", "d", "e"])
print(data, "\n")

# キーの有無を確認する
print("c" in data)
print("z" in data)
【実行結果】
a    1
b    2
c    3
d    4
e    5
dtype: int64 

True
False

上記の例では、"c""z"がインデックスに含まれているかを確認しています。"c"は含まれるので結果はTrueとなっていますが、"z"は含まれていないため、Falseとなっています。キーが含まれるかどうかを辞書で確認する方法と同様です。

NumPy配列と同様のデータ選択方法

pandasのSeriesは、NumPy配列(ndarray)と同様にスライス、マスキング、ファンシーインデックスといったデータ選択が可能です。

スライスでのデータ選択

Seriesは、スライスによりデータを選択することができます。

import pandas as pd

data = pd.Series([1, 2, 3, 4, 5], index=["a", "b", "c", "d", "e"])
print(data, "\n")

# スライスでのアクセス
print(data["b":"d"], "\n")
print(data[0:2])
【実行結果】
a    1
b    2
c    3
d    4
e    5
dtype: int64 

b    2
c    3
d    4
dtype: int64 

a    1
b    2
dtype: int64

上記のdata["b":"d"]のように、インデックスの文字列に対してもスライスでのアクセスができます。このようにindex=で指定してあるインデックスは明示的なインデックス(explicit index)と言います。

一方で、data[0:2]は、index=に指定していない数値ですが、NumPyの配列にアクセスできるのと同様に要素にアクセスができます。このようなインデックスを、暗黙的なインデックス(implicit index)と言います。

上記の出力結果で注目するべきポイントとしては、data["b":"d"]では末尾の"d"が指す値を含んでいるのに対して、data[0:2]の場合は末尾の2が指す値は含んでいない点です。

この点が少しややこしくなる要因のため、pandasでは明示的なインデックスと暗黙的なインデックスを明確に区別するために後述するlocメソッドとilocメソッドが用意されています。具体的な使用方法については後述します。

明示的なインデックス(explicit index)と暗黙的なインデックス(implicit index)

条件によるマスキング

Seriesに含まれる要素の中で特定の条件(値の大小など)に一致する値のみを選択する場合には、NumPy配列と同様で以下のように条件によるマスキングができます。

import pandas as pd

data = pd.Series([1, 2, 3, 4, 5], index=["a", "b", "c", "d", "e"])
print(data, "\n")

# マスキング
print(f"data > 1:\n{data > 1}\n")
print(f"data < 5:\n{data < 5}\n")
print(f"(data > 1) & (data < 5):\n{(data > 1) & (data < 5)}\n")
print(f"data[(data > 1) & (data < 5)]:\n{data[(data > 1) & (data < 5)]}")
【実行結果】
a    1
b    2
c    3
d    4
e    5
dtype: int64 

data > 1:
a    False
b     True
c     True
d     True
e     True
dtype: bool

data < 5:
a     True
b     True
c     True
d     True
e    False
dtype: bool

(data > 1) & (data < 5):
a    False
b     True
c     True
d     True
e    False
dtype: bool

data[(data > 1) & (data < 5)]:
b    2
c    3
d    4
dtype: int64

data>1data<5(data > 1) & (data < 5)といった演算の結果は、bool型のSeiesとなります。そして、上記例のdata[(data > 1) & (data < 5)]のように、条件式のbool値を指定することでマスキングしてデータを選択することができます。

ファンシーインデックスによるアクセス

Seriesは、NumPyと同様にファンシーインデックスの考え方でデータを選択することができます。ファンシーインデックスは、インデックスの順序を指定する配列を渡すことで対象の要素を取り出す方法です。ファンシーインデックの基本については「ファンシーインデックス(Fancy Indexing)の基本」でまとめていますので興味があれば参考にしてください。

import pandas as pd

data = pd.Series([1, 2, 3, 4, 5], index=["a", "b", "c", "d", "e"])
print(data, "\n")

# ファンシーインデックス
print(data[["c", "d", "a"]])
【実行結果】
a    1
b    2
c    3
d    4
e    5
dtype: int64 

c    3
d    4
a    1
dtype: int64

上記の例では、["c", "d", "a"]のインデックス順のリストを渡しています。これにより、指定したインデックス順でデータが取得できていることが分かります。データの並べ替えに使用すると便利です。

pandasのデータ選択方法(loc、ilocメソッド)

pandasで特有なデータの選択方法として、locメソッド、ilocメソッドを用いたデータ選択ができます。

  • locメソッド:明示的なインデックス(explicit index)に対してデータ選択
  • ilocメソッド:暗黙的なインデックス(implicit index)に対してデータ選択

スライスでのデータ選択と複雑さ

スライスでデータをアクセスするときに、明示的なインデックスと暗黙的なインデックスが双方に数値であった場合に発生する少し複雑な例について見てみましょう。

import pandas as pd

data = pd.Series(["a", "b", "c", "d", "e"], index=[1, 2, 3, 4, 5])
print(data, "\n")

# 要素を参照(明示的なインデックスを参照)
print(data[1], "\n")
# スライスによるアクセス(暗黙的なインデックスを参照)
print(data[1:4])
【実行結果】
1    a
2    b
3    c
4    d
5    e
dtype: object 

a 

2    b
3    c
4    d
dtype: object

この例で、data[1]は明示的インデックスを使ってアクセスしているため、結果は「a」です。一方で、スライスで指定しているdata[1:4]については、暗黙的なインデックスを参照しているため、結果は「b, c, d」となっています。

プログラム上は同じ1に見えるのにアクセスしている位置が異なっている状況で、プログラム動作を理解する際に複雑になります。

明示的なインデックス(explicit index)と暗黙的なインデックス(implicit index)のややこしさ

pandasでは、このような複雑さがなくなるように、後述するlocメソッドとilocメソッドが用意されており、それぞれ明確に使い分けられるようになっています。

locメソッドによるデータ選択(明示的なインデックス)

locメソッドは、「明示的なインデックス(explicit index)」に対してデータを取得する際に使用します。

import pandas as pd

data = pd.Series(["a", "b", "c", "d", "e"], index=[1, 2, 3, 4, 5])
print(data, "\n")

# locメソッドでデータ選択(明示的なインデックス)
print(data.loc[1], "\n")
print(data.loc[1:3])
【実行結果】
1    a
2    b
3    c
4    d
5    e
dtype: object 

a 

1    a
2    b
3    c
dtype: object

locメソッドでは、明示的なインデックスを指定して要素にアクセスします。また、スライスでは最後のインデックスが指す値を含む点に注意しましょう。

locメソッド 明示的なインデックス(implicit index)

ilocメソッドによるデータ選択(暗黙的なインデックス)

ilocメソッドは、「明示的なインデックス(implicit index)」に対してデータを取得する際に使用します。

import pandas as pd

data = pd.Series(["a", "b", "c", "d", "e"], index=[1, 2, 3, 4, 5])
print(data, "\n")

# ilocメソッドでデータ選択(暗黙的なインデックス)
print(data.iloc[1], "\n")
print(data.iloc[1:3])
【実行結果】
1    a
2    b
3    c
4    d
5    e
dtype: object 

b 

2    b
3    c
dtype: object

ilocメソッドでは、暗黙的ななインデックスを指定して要素にアクセスします。また、スライスでは最後のインデックスが指す値を含まない点に注意しましょう。

ilocメソッド 暗黙的なインデックス(implicit index)

まとめ

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

pandasのSeriesのデータ選択方法には、以下のようにいくつかの種類があります。

  • Pythonの辞書と同様のデータ選択方法
  • NumPy配列と同様のデータ選択方法
  • pandasのデータ選択方法(locメソッド、ilocメソッド)

上記のアクセス方法について例を使って紹介してきました。特にpandasのデータ選択方法であるlocメソッド、ilocメソッドについては使い方をよく理解してもらうとよいかと思います。状況に応じてうまく使いこなしてデータを扱えるようになりましょう。