pandas.DataFrameの行番号、列番号を取得

Posted: | Tags: Python, pandas

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.DataFrameindex, 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, columnslist()によって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.DataFrameindexをリスト化すると、特定の値の行名のリストが取得できる。

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

関連カテゴリー

関連記事