pandas.DataFrameの行番号、列番号を取得
pandas.DataFrameの行名、列名から行番号、列番号を取得したり、列の要素の値から行名、行番号を取得したりする方法を説明する。
以下の内容について説明する。
- 行名、列名から行番号、列番号を取得
get_loc()メソッド- 行名、列名が重複している場合
index,columnsをリスト化
- 列の要素の値から行名、行番号を取得
行番号、列番号から行、列や要素の値を取得したい場合は以下の記事を参照。
以下のpandas.DataFrameを例とする。
import pandas as pd
df = pd.read_csv('data/src/sample_pandas_normal.csv', index_col=0)
print(df)
# age state point
# name
# Alice 24 NY 64
# Bob 42 CA 92
# Charlie 18 CA 70
# Dave 68 TX 70
# Ellen 24 CA 88
# Frank 30 NY 57
サンプルのCSVファイルはこちら。
行名、列名から行番号、列番号を取得
get_loc()メソッド
pandas.DataFrameのindex, columnsにはget_loc()というメソッドがある。
行名または列名を引数に指定するとその行番号、列番号が返される。行番号、列番号ともに0始まりの整数。
行番号はindexから取得。
print(df.index.get_loc('Alice'))
# 0
print(df.index.get_loc('Ellen'))
# 4
列番号はcolumnsから取得。
print(df.columns.get_loc('age'))
# 0
print(df.columns.get_loc('point'))
# 2
いずれの場合も存在しない名前に対してはエラーKeyErrorとなる。
# print(df.index.get_loc('XXX'))
# KeyError: 'XXX'
# print(df.columns.get_loc('XXX'))
# KeyError: 'XXX'
行名、列名が重複している場合
行名、列名が重複している場合は注意が必要。以下、行名が重複している場合を例とするが、列名の場合も同じ。
rename()メソッドで行名を変更し、重複した行名を準備。
df_dup = df.rename(index={'Charlie': 'Bob'})
print(df_dup)
# age state point
# name
# Alice 24 NY 64
# Bob 42 CA 92
# Bob 18 CA 70
# Dave 68 TX 70
# Ellen 24 CA 88
# Frank 30 NY 57
この場合、get_loc()メソッドは行番号ではなくslice型オブジェクトを返す。
print(df_dup.index.get_loc('Bob'))
# slice(1, 3, None)
print(type(df_dup.index.get_loc('Bob')))
# <class 'slice'>
さらに重複した行名を増やす。
df_dup.rename(index={'Ellen': 'Bob'}, inplace=True)
print(df_dup)
# age state point
# name
# Alice 24 NY 64
# Bob 42 CA 92
# Bob 18 CA 70
# Dave 68 TX 70
# Bob 24 CA 88
# Frank 30 NY 57
スライスで表せない場合はbool型のNumPy配列numpy.ndarrayとなる。
print(df_dup.index.get_loc('Bob'))
# [False True True False True False]
print(type(df_dup.index.get_loc('Bob')))
# <class 'numpy.ndarray'>
スライスオブジェクトもbool型の配列もインデックス参照やilocの位置指定に使用できる。bool型配列はlocでも使用可能。
print(df_dup[df_dup.index.get_loc('Bob')])
# age state point
# name
# Bob 42 CA 92
# Bob 18 CA 70
# Bob 24 CA 88
print(df_dup.iloc[df_dup.index.get_loc('Bob'), 0])
# name
# Bob 42
# Bob 18
# Bob 24
# Name: age, dtype: int64
なお、indexに対してはわざわざget_loc()でスライスオブジェクトやbool型配列を取得しなくてもquery()メソッドで要素を抽出できる。
print(df_dup.query('index == "Bob"'))
# age state point
# name
# Bob 42 CA 92
# Bob 18 CA 70
# Bob 24 CA 88
行名、列名が重複している場合でもスライスオブジェクトやbool型配列ではなく行番号、列番号を取得したい場合は次に説明するようにindex, columnsをリスト化する。
index, columnsをリスト化
index, columnsはlist()によってPython標準のリスト(list型オブジェクト)に変換できる。
l_index = list(df.index)
print(l_index)
# ['Alice', 'Bob', 'Charlie', 'Dave', 'Ellen', 'Frank']
print(type(l_index))
# <class 'list'>
l_columns = list(df.columns)
print(l_columns)
# ['age', 'state', 'point']
print(type(l_columns))
# <class 'list'>
リストのindex()メソッドでインデックス(何番目の要素か)を取得可能。
print(l_index.index('Bob'))
# 1
行名が重複している場合は組み込み関数enumerate()とリスト内包表記を利用することでインデックスのリストを取得できる。
l_index_dup = list(df_dup.index)
print(l_index_dup)
# ['Alice', 'Bob', 'Bob', 'Dave', 'Bob', 'Frank']
print([i for i, x in enumerate(l_index_dup) if x == 'Bob'])
# [1, 2, 4]
詳細は以下の記事を参照。
列の要素の値から行名、行番号を取得
行名、列名から行番号、列番号を取得するのではなく、任意の列の要素から対応する行名および行番号を取得する方法を示す。
引き続き以下のpandas.DataFrameを例とする。
print(df)
# age state point
# name
# Alice 24 NY 64
# Bob 42 CA 92
# Charlie 18 CA 70
# Dave 68 TX 70
# Ellen 24 CA 88
# Frank 30 NY 57
行名の取得
query()メソッドで任意の列の要素に対する条件で行を抽出できる。返り値はpandas.DataFrame。
print(df.query('state == "CA"'))
# age state point
# name
# Bob 42 CA 92
# Charlie 18 CA 70
# Ellen 24 CA 88
query()で抽出したpandas.DataFrameのindexをリスト化すると、特定の値の行名のリストが取得できる。
print(list(df.query('state == "CA"').index))
# ['Bob', 'Charlie', 'Ellen']
抽出されるのが1行の場合も同じ。リストではなく行名の値が欲しい場合はindexの最初の要素[0]を取得すればOK。
print(df.query('state == "TX"'))
# age state point
# name
# Dave 68 TX 70
print(list(df.query('state == "TX"').index))
# ['Dave']
print(df.query('state == "TX"').index[0])
# Dave
行番号の取得
行名ではなく行番号を取得したい場合は、reset_index()でindexを0始まりの連番にリセットしてから同様の処理を行う。
print(df.reset_index())
# name age state point
# 0 Alice 24 NY 64
# 1 Bob 42 CA 92
# 2 Charlie 18 CA 70
# 3 Dave 68 TX 70
# 4 Ellen 24 CA 88
# 5 Frank 30 NY 57
print(list(df.reset_index().query('state == "CA"').index))
# [1, 2, 4]
print(list(df.reset_index().query('state == "TX"').index))
# [3]
print(df.reset_index().query('state == "TX"').index[0])
# 3