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