pandasのDataFrameのlocインデクサは行、列の順で絞り込む(例:df.loc[df["b"]>12, "a"]) (original) (raw)

はじめに

いくおです。 nikkieです。

Today(※最近) I learned です。

目次

動作環境

% uv version uv 0.4.27 (Homebrew 2024-10-25) % uv run --python 3.12 --with pandas python

import pandas as pd pd.version '2.2.3'

[]を2回使って行と列を指定するも、そこに代入できていない

DataFrameを作ります

df = pd.DataFrame({"a": [11, 21, 31], "b": [12, 22, 32], "c": [13, 23, 33]}) df a b c 0 11 12 13 1 21 22 23 2 31 32 33

b列が12より大きい行(すなわち、インデックスが1と2の行)を取り出すと

df[df["b"]>12] a b c 1 21 22 23 2 31 32 33

そのa列は

df[df["b"]>12]["a"] 1 21 2 31 Name: a, dtype: int64

以上から、b列が12より大きい行のa列の値を書き換えようとすると

df[df["b"]>12]["a"] = 99 :1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html

例外が送出されたわけではないですが、dfは変わっていません(dfのコピーでだけa列の値が変わったのかな?)

df a b c 0 11 12 13 1 21 22 23 2 31 32 33

locを使ってアクセス・代入してみる

警告で案内された.loc[row_indexer,col_indexer]を試します1
今回理解したのは、**.loc[行を絞る,列を絞る]** ということです。

b列が12より大きい行

df.loc[df["b"]>12] a b c 1 21 22 23 2 31 32 33

b列が12より大きい行のa列

df.loc[df["b"]>12, "a"] 1 21 2 31 Name: a, dtype: int64

書き換えられます!!

df.loc[df["b"]>12, "a"] = 99 df a b c 0 11 12 13 1 99 22 23 2 99 32 33

『pandasクックブック』にあたる

古い本ですが、手元の『pandasクックブック』よりdf.loc[rows, columns]という書式について

カンマの左側の選択は、行インデックスによる行選択、カンマの右側は常にカラムインデックスによるカラム選択だ。(p.79)

またクックブックでは、

と呼んでいました (p.73)

終わりに

pandasのDataFrameでlocインデクサは行->列の順で絞れる(df.loc[rows, columns])ことを理解しました。
今回の例では、df["b"]>12行を絞り、それらの列を"a"で指定しました。
インデックス演算子で指定して値を代入したところ元が書き換わりませんでしたが、locインデクサを使うと書き換えられました!

pandasを知ってからlocインデクサは自分のものにできていない感じでしたが、今回で完全に理解しました!