pandasで任意の位置の値を取得・変更するat, iat, loc, iloc | note.nkmk.me (2024)

pandas.DataFrameの任意の位置のデータを取り出したり変更(代入)したりするには、at, iat, loc, ilocを使う。at()ではなくat[]のように記述する。

位置の指定方法および選択できる範囲に違いがある。

  • 位置の指定方法
    • at, loc: 行名(行ラベル)、列名(列ラベル)
    • iat, iloc: 行番号、列番号
  • 選択し取得・変更できるデータ
    • at, iat: 単独の要素の値
    • loc, iloc: 単独および複数の要素の値
      • リストやスライスで範囲を指定可能
      • 単独の要素にアクセスする場合はatiatのほうが高速

目次

  • at, iat: 単独の要素の値を選択、取得・変更
  • loc, iloc: 単独および複数の要素の値を選択、取得・変更
    • 単独の要素の値を選択
    • 複数の要素の値を選択(リスト・スライスで範囲指定)
    • 行・列を選択
    • boolのリストによるマスク(ブーリアンインデックス)
  • 行名・列名が重複している場合
  • 番号と名前(ラベル)で位置を指定
  • 行をpandas.Seriesで選択する際の暗黙の型変換

pandas.DataFrameの行・列、pandas.Seriesの要素を選択する場合はインデックス参照df[]も使用できる。

  • 関連記事: pandasのインデックス指定で行・列を抽出

なお、以前あったget_value()およびix[]は、バージョン1.0で削除された。

本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。以下のpandas.DataFrameを例とする。

import pandas as pdprint(pd.__version__)# 2.0.3df = pd.DataFrame({'col_0': ['00', '10', '20', '30', '40'], 'col_1': ['01', '11', '21', '31', '41'], 'col_2': ['02', '12', '22', '32', '42'], 'col_3': ['03', '13', '23', '33', '43']}, index=['row_0', 'row_1', 'row_2', 'row_3', 'row_4'])print(df)# col_0 col_1 col_2 col_3# row_0 00 01 02 03# row_1 10 11 12 13# row_2 20 21 22 23# row_3 30 31 32 33# row_4 40 41 42 43

at, iat: 単独の要素の値を選択、取得・変更

atは行名と列名で位置を指定する。

データを取得するだけでなく、その位置に新たな値を設定(代入)することもできる。

print(df.at['row_1', 'col_2'])# 12df.at['row_1', 'col_2'] = '0'print(df.at['row_1', 'col_2'])# 0

iatは行番号と列番号で位置を指定する。行番号・列番号は0始まり。

atと同じく、データを取得するだけでなく、その位置に新たな値を設定(代入)できる。

print(df.iat[1, 2])# 0df.iat[1, 2] = '12'print(df.iat[1, 2])# 12

loc, iloc: 単独および複数の要素の値を選択、取得・変更

locilocは、単独の値だけでなく範囲を指定して複数のデータを選択できる。locは行名と列名、ilocは行番号と列番号で位置を指定する。

単独の要素の値を選択

単独の値にアクセスする場合はat, iatと同じ。処理速度はat, iatのほうが速い。

print(df.loc['row_1', 'col_2'])# 12print(df.iloc[1, 2])# 12

データを取得するだけでなく、その位置に新たな値を設定(代入)することもできる。

df.loc['row_1', 'col_2'] = '0'print(df.loc['row_1', 'col_2'])# 0df.iloc[1, 2] = '12'print(df.iloc[1, 2])# 12

複数の要素の値を選択(リスト・スライスで範囲指定)

loc, ilocでは、行名や列番号などのスカラー値のほか、リスト[a, b, c, ...]やスライスstart:stop:stepでデータの範囲・位置を指定して複数の値にアクセスできる。

スライスの書き方は通常のスライスと同じ。stepは省略可。

  • 関連記事: Pythonのスライスによるリストや文字列の部分選択・代入

スライスstart:stop:stepで指定するとき、loc(行名・列名)ではstopの要素も含まれるので注意。iloc(行番号・列番号)では通常のスライスと同様にstopの一つ前まで。

また、リストで指定すると、行や列の順番は指定したリストの順番になる。

print(df.loc['row_1':'row_3', ['col_2', 'col_0']])# col_2 col_0# row_1 12 10# row_2 22 20# row_3 32 30print(df.iloc[1:3, [2, 0]])# col_2 col_0# row_1 12 10# row_2 22 20

スライスでstepを指定すると、奇数行・偶数行を抽出したりできる。

print(df.iloc[::2, [0, 3]])# col_0 col_3# row_0 00 03# row_2 20 23# row_4 40 43print(df.iloc[1::2, [0, 3]])# col_0 col_3# row_1 10 13# row_3 30 33

複数の値を一括で変更することが可能。スカラー値を代入するとすべての要素がその値になる。範囲に対して代入する場合は、二次元リスト(リストのリスト)や二次元のNumPy配列ndarrayなどを使う。

df.iloc[1:3, [2, 0]] = '0'print(df)# col_0 col_1 col_2 col_3# row_0 00 01 02 03# row_1 0 11 0 13# row_2 0 21 0 23# row_3 30 31 32 33# row_4 40 41 42 43df.iloc[1:3, [2, 0]] = [['12', '10'], ['22', '20']]print(df)# col_0 col_1 col_2 col_3# row_0 00 01 02 03# row_1 10 11 12 13# row_2 20 21 22 23# row_3 30 31 32 33# row_4 40 41 42 43

なお、行・列をスカラー値で指定して一行・一列を選択するとpandas.Seriesが返されるが、同じ一行・一列でも、スライスやリストで指定するとpandas.DataFrameとなる。

特に、行をpandas.Seriesで取得すると暗黙の型変換が行われる可能性があるので要注意。詳細は後述。

print(df.loc['row_1', ['col_0', 'col_2']])print(type(df.loc['row_1', ['col_0', 'col_2']]))# col_0 10# col_2 12# Name: row_1, dtype: object# <class 'pandas.core.series.Series'>print(df.loc['row_1':'row_1', ['col_0', 'col_2']])print(type(df.loc['row_1':'row_1', ['col_0', 'col_2']]))# col_0 col_2# row_1 10 12# <class 'pandas.core.frame.DataFrame'>print(df.loc[['row_1'], ['col_0', 'col_2']])print(type(df.loc[['row_1'], ['col_0', 'col_2']]))# col_0 col_2# row_1 10 12# <class 'pandas.core.frame.DataFrame'>

行・列を選択

インデックス参照df[]で行・列を選択できるが、以下の指定方法に限られる。

  • 行の選択: 行名・行番号のスライス
  • 列の選択: 列名、または、列名のリスト

詳細は以下の記事を参照。

  • 関連記事: pandasのインデックス指定で行・列を抽出
print(df['row_1':'row_3'])# col_0 col_1 col_2 col_3# row_1 10 11 12 13# row_2 20 21 22 23# row_3 30 31 32 33print(df[1:3])# col_0 col_1 col_2 col_3# row_1 10 11 12 13# row_2 20 21 22 23print(df['col_1'])# row_0 01# row_1 11# row_2 21# row_3 31# row_4 41# Name: col_1, dtype: objectprint(df[['col_1', 'col_3']])# col_1 col_3# row_0 01 03# row_1 11 13# row_2 21 23# row_3 31 33# row_4 41 43

loc, ilocを使うと、より柔軟に行・列を指定できる。

loc, ilocで列の指定を省略すると行が選択できる。行名・行番号単独での指定やリストによる指定も可能。

print(df.loc['row_2'])# col_0 20# col_1 21# col_2 22# col_3 23# Name: row_2, dtype: objectprint(df.iloc[[1, 3]])# col_0 col_1 col_2 col_3# row_1 10 11 12 13# row_3 30 31 32 33

loc, ilocで行の指定を:(全体のスライス)にすると列を選択できる。スライスによる指定やilocでの列番号による指定も可能。

print(df.loc[:, 'col_1':])# col_1 col_2 col_3# row_0 01 02 03# row_1 11 12 13# row_2 21 22 23# row_3 31 32 33# row_4 41 42 43print(df.iloc[:, 2])# row_0 02# row_1 12# row_2 22# row_3 32# row_4 42# Name: col_2, dtype: object

上述のように、行・列をスカラー値で指定して一行・一列を選択するとpandas.Seriesが返されるが、同じ一行・一列でも、スライスやリストで指定するとpandas.DataFrameとなる。

特に、行をpandas.Seriesで選択すると暗黙の型変換が行われる可能性があるので要注意。詳細は後述。

print(df.loc['row_2'])print(type(df.loc['row_2']))# col_0 20# col_1 21# col_2 22# col_3 23# Name: row_2, dtype: object# <class 'pandas.core.series.Series'>print(df.loc['row_2':'row_2'])print(type(df.loc['row_2':'row_2']))# col_0 col_1 col_2 col_3# row_2 20 21 22 23# <class 'pandas.core.frame.DataFrame'>print(df.loc[['row_2']])print(type(df.loc[['row_2']]))# col_0 col_1 col_2 col_3# row_2 20 21 22 23# <class 'pandas.core.frame.DataFrame'>

boolのリストによるマスク(ブーリアンインデックス)

loc, ilocでは、bool値(True, False)のリストやnumpy.ndarrayを指定してデータをマスクすることができる。例では行に指定しているが、列に指定することも可能。

l_bool = [True, False, False, True, False]print(df.loc[l_bool, ['col_0', 'col_2']])# col_0 col_2# row_0 00 02# row_3 30 32print(df.iloc[l_bool, [0, 2]])# col_0 col_2# row_0 00 02# row_3 30 32

要素数が一致していないとエラー。

l_bool_wrong = [True, False, False]# print(df.loc[l_bool_wrong, ['col_0', 'col_2']])# IndexError: Boolean index has wrong length: 3 instead of 5

locではbool値を要素とするpandas.Seriesも指定可能。順番ではなくラベルを元にマスクされる。

s_bool = pd.Series([True, False, False, True, False], index=reversed(df.index))print(s_bool)# row_4 True# row_3 False# row_2 False# row_1 True# row_0 False# dtype: boolprint(df.loc[s_bool, ['col_0', 'col_2']])# col_0 col_2# row_1 10 12# row_4 40 42

ilocではpandas.Seriesは指定不可。

# print(df.iloc[s_bool, [0, 2]])# ValueError: Location based indexing can only have [integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array] types

locでも要素数やラベルが一致していないとエラー。

s_bool_wrong = pd.Series([True, False, False], index=['row_0', 'row_1', 'row_2'])# print(df.loc[s_bool_wrong, ['col_0', 'col_2']])# IndexingError: Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match).s_bool_wrong = pd.Series([True, False, False, True, False], index=['row_0', 'row_1', 'row_2', 'row_3', 'XXX'])# print(df.loc[s_bool_wrong, ['col_0', 'col_2']])# IndexingError: Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match).

行名・列名が重複している場合

行名index、列名columnsに重複する値が含まれていてもエラーにならない。

重複する行名・列名を持つpandas.DataFrameを例とする。

df_duplicated = df.rename(columns={'col_2': 'col_1'}, index={'row_3': 'row_2'})print(df_duplicated)# col_0 col_1 col_1 col_3# row_0 00 01 02 03# row_1 10 11 12 13# row_2 20 21 22 23# row_2 30 31 32 33# row_4 40 41 42 43

at, locでは、重複したラベルを指定すると該当の複数要素が選択される。

print(df_duplicated.at['row_2', 'col_1'])print(type(df_duplicated.at['row_2', 'col_1']))# col_1 col_1# row_2 21 22# row_2 31 32# <class 'pandas.core.frame.DataFrame'>print(df_duplicated.loc[:'row_2', ['col_1', 'col_3']])print(type(df_duplicated.loc[:'row_2', ['col_1', 'col_3']]))# col_1 col_1 col_3# row_0 01 02 03# row_1 11 12 13# row_2 21 22 23# row_2 31 32 33# <class 'pandas.core.frame.DataFrame'>

iat, ilocで行番号・列番号で指定する場合は、位置を基準とするのでラベルが重複していても特に問題ない。

print(df_duplicated.iat[2, 1])# 21print(df_duplicated.iloc[:2, [1, 3]])# col_1 col_3# row_0 01 03# row_1 11 13

混乱のもとになるので、強い理由がないのであれば行名・列名は一意の値にしたほうがよい。

行名・列名が一意の値になっている(重複していない)かどうかはindex.is_unique, columns.is_uniqueで確認できる。

print(df_duplicated.index.is_unique)# Falseprint(df_duplicated.columns.is_unique)# False

行名・列名の変更については以下の記事を参照。

  • 関連記事: pandas.DataFrameの行名・列名の変更

番号と名前(ラベル)で位置を指定

行番号と列名(列ラベル)のように番号と名前(ラベル)の組み合わせで位置を指定したい場合、atまたはlocindex, column属性を使う方法がある。

index, column属性で行番号または列番号からその行名・列名を取得できる。

print(df.index[2])# row_2print(df.columns[2])# col_2

スライスやリストを指定して複数の行名・列名を取得することも可能。

print(df.index[1:4])# Index(['row_1', 'row_2', 'row_3'], dtype='object')print(df.columns[[1, 3]])# Index(['col_1', 'col_3'], dtype='object')

これを利用すると、atまたはlocで番号と名前の組み合わせで位置を指定できる。

print(df.at[df.index[2], 'col_2'])# 22print(df.loc[['row_0', 'row_3'], df.columns[[1, 3]]])# col_1 col_3# row_0 01 03# row_3 31 33

以下のように[]loc,ilocを繰り返す書き方もできるが、これはchained indexingと呼ばれ、SettingWithCopyWarningという警告の要因となる。

  • 関連記事: pandasのSettingWithCopyWarningの対処法

データを取得・確認するだけであれば問題ないが、新たな値を代入すると想定外の結果となる場合があるので注意。

print(df['col_2'][2])# 22print(df.loc[['row_0', 'row_3']].iloc[:, [1, 3]])# col_1 col_3# row_0 01 03# row_3 31 33

行をpandas.Seriesで選択する際の暗黙の型変換

locilocで一行を選択してpandas.Seriesで取得する場合、元のpandas.DataFrameの各列のデータ型dtypeが異なっていると暗黙の型変換が行われる。

  • 関連記事: pandasのデータ型dtype一覧とastypeによる変換(キャスト)

整数intの列と浮動小数点数floatの列を持つpandas.DataFrameを例とする。

df_mix = pd.DataFrame({'col_int': [0, 1, 2], 'col_float': [0.1, 0.2, 0.3]}, index=['A', 'B', 'C'])print(df_mix)# col_int col_float# A 0 0.1# B 1 0.2# C 2 0.3print(df_mix.dtypes)# col_int int64# col_float float64# dtype: object

locilocで一行をpandas.Seriesとして取得すると、そのデータ型はfloatとなる。intの列にあった要素はfloatに変換される。

print(df_mix.loc['B'])# col_int 1.0# col_float 0.2# Name: B, dtype: float64print(type(df_mix.loc['B']))# <class 'pandas.core.series.Series'>

以下のように[]を続けて書くと、floatに変換されたpandas.Seriesの要素が返される。元の型と異なる型として要素の値が返されてしまうので要注意。

print(df_mix.loc['B']['col_int'])# 1.0print(type(df_mix.loc['B']['col_int']))# <class 'numpy.float64'>

[]loc,ilocを繰り返す書き方は避けてatiatを使えば、元の型の要素が取得できる。

print(df_mix.at['B', 'col_int'])# 1print(type(df_mix.at['B', 'col_int']))# <class 'numpy.int64'>

なお、locilocにおいてリストやスライスで一行を選択した場合は、pandas.Seriesではなくpandas.DataFrameが返される。この場合は元のデータ型dtypeが保持される。

print(df_mix.loc[['B']])# col_int col_float# B 1 0.2print(type(df_mix.loc[['B']]))# <class 'pandas.core.frame.DataFrame'>print(df_mix.loc[['B']].dtypes)# col_int int64# col_float float64# dtype: object
pandasで任意の位置の値を取得・変更するat, iat, loc, iloc | note.nkmk.me (2024)
Top Articles
Latest Posts
Article information

Author: Duane Harber

Last Updated:

Views: 5767

Rating: 4 / 5 (71 voted)

Reviews: 94% of readers found this page helpful

Author information

Name: Duane Harber

Birthday: 1999-10-17

Address: Apt. 404 9899 Magnolia Roads, Port Royceville, ID 78186

Phone: +186911129794335

Job: Human Hospitality Planner

Hobby: Listening to music, Orienteering, Knapping, Dance, Mountain biking, Fishing, Pottery

Introduction: My name is Duane Harber, I am a modern, clever, handsome, fair, agreeable, inexpensive, beautiful person who loves writing and wants to share my knowledge and understanding with you.