インデックスについて理解を深めるために、軸について説明をします。軸とは、方向を表すものです。
DataFrameの軸は、「インデックス(index)」と「列名一覧(columns)」の2つです。それぞれ、縦の方向、横の方向になります。
Seriesの軸は1つです。Seriesには縦や横の概念はないですが、Seriesの軸はインデックスです。ここでいうインデックスとは、第1の軸を意味します。
DataFrameの行でもDataFrameの列でも、Seriesの軸はインデックスです。したがって、次のようになります。
- 「DataFrameの特定の列」のインデックスは、元のDataFrameのインデックスです。
- 「DataFrameの特定の行」のインデックスは、元のDataFrameの列名一覧です。
※ PyQでは、インデックスの要素を「行名」と呼びますが、必ずしも行方向とは限らないことに注意してください。
「特定行のインデックスが元のDataFrameの列名一覧になる」点について、具体的な例で確認してみましょう。下記のコードでは、df.loc[0]
は1行目に当たるSeriesです。そして、そのindex
は列名一覧(df.columns
)です。
df = pd.DataFrame(
[["Alice", 17], ["Bob", 24], ["Carol", 29]],
columns=["Name", "Age"],
)
print(df.loc[0].index) # Index(['Name', 'Age'], dtype='object')
print(df.columns) # Index(['Name', 'Age'], dtype='object')
※ 軸の概念は、pandasのメソッドや関数で処理の方向を指定する際に必要になります。軸を指定する引数にはaxisという単語が使われます。axisという引数を使うメソッドについては、クエスト「欠損値を学ぼう」などで学習します。
行の要素の取得
import pandas as pd
df = pd.DataFrame(
[["Alice", 17], ["Bob", 24]],
columns=["Name", "Age"],
)
df
Name | Age | |
---|---|---|
0 | Alice | 17 |
1 | Bob | 24 |
列Name
のindex
は、df
のインデックスです。
print(df.Name.index) print(df.index) →この二つの書き方が同じものを示す。だからprintしている。
RangeIndex(start=0, stop=2, step=1) RangeIndex(start=0, stop=2, step=1)
1行目のindex
は、df
の列名一覧です。
print(df.loc[0].index) print(df.columns)
Index(['Name', 'Age'], dtype='object') Index(['Name', 'Age'], dtype='object')
列の要素の取得
これまで、sr[列名]とすることでSeriesの要素を取得できることを学びました。
DataFrameの列(たとえばdf.列名)はSeriesなので、同じ方法で列の要素の取得が可能です。
すなわち、df.列名[行名]とすることで、DataFrameの指定した列名・行名の要素の値を取得できます。
下記のDataFrameの変数dfを考えましょう。
Name | Age | |
---|---|---|
10 | Alice | 17 |
20 | Bob | 24 |
行名が10
で、列名がAge
のデータを取得したいとします。
df.Age
はDataFrameの列であり、df.Age[10]
で取得できます。
パート「pandasのデータ構造(DataFrame)」では、同じ値をdf.loc[10, "Age"]
で取得しました。
このように、df.列名[行名]
は、df.loc[行名, 列名]
を省略した書き方になっています。
要素の変更
これまでは、sr[行名] = 新しい値
とすることでSeriesの要素を変更できることを学びました。
しかし取得と違い、列の変更はSeriesと同じ方法ではできないことがあります(実行すると警告が出ます)。
# 列の変更(非推奨)
df.列名[行名] = 新しい値
そのため、DataFrameの列の要素を更新したい場合は、loc
を使って次のように書きます。
# 列の変更(推奨)
df.loc[行名, 列名] = 新しい値
たとえば、df.loc[10, “Age”] = …のように使います。
DataFrameの列であるdf.Ageを通してdf.Age[10] = …のように値を変更することは推奨されません。
理由は、値が変更できない可能性があるからです。
演習
import pandas as pd
df = pd.DataFrame(
[["Alice", 17], ["Bob", 24]],
index=[10, 20],
columns=["Name", "Age"],
)
df
Name | Age | |
---|---|---|
10 | Alice | 17 |
20 | Bob | 24 |
まずはloc
を使って、行名が10
で、列名がAge
の値を取得します(復習)。
df.loc[10, "Age"]
17
loc
を使わずに、列Age
に対して、行名が10
の値を取得します。
df.Age[10]
17
DataFrameの値を更新するときは、df.loc[...] = ...
を使いましょう。
df.loc[10, "Age"] = 18
df
Name | Age | |
---|---|---|
10 | Alice | 18 |
20 | Bob | 24 |
DataFrameの列に対して、行名を使うと警告が出ます。取得とは違って、下記の方法は非推奨です。
df.Age[10] = 18
/tmp/ipykernel_11/2969545342.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy df.Age[10] = 18
コメント