Dataframeの軸

インデックスについて理解を深めるために、軸について説明をします。軸とは、方向を表すものです。

DataFrameの軸は、「インデックス(index)」と「列名一覧(columns)」の2つです。それぞれ、縦の方向、横の方向になります。

https://images.pyq.jp/repo/prod/pandas_structure_series_v2/pandas_structure_dataframe_ax.jpg

Seriesの軸は1つです。Seriesには縦や横の概念はないですが、Seriesの軸はインデックスです。ここでいうインデックスとは、第1の軸を意味します。

https://images.pyq.jp/repo/prod/pandas_structure_series_v2/pandas_structure_series_ax.jpg

DataFrameの行でもDataFrameの列でも、Seriesの軸はインデックスです。したがって、次のようになります。

  • 「DataFrameの特定の」のインデックスは、元のDataFrameのインデックスです。
  • 「DataFrameの特定の」のインデックスは、元のDataFrameの列名一覧です。
https://images.pyq.jp/repo/prod/pandas_structure_series_v2/pandas_structure_dataframe_rc.jpg

※ 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
NameAge
0Alice17
1Bob24

Nameindexは、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を考えましょう。

NameAge
10Alice17
20Bob24

行名が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
NameAge
10Alice17
20Bob24

まずはlocを使って、行名が10で、列名がAgeの値を取得します(復習)。

df.loc[10, "Age"]
17

locを使わずに、列Ageに対して、行名が10の値を取得します。

df.Age[10]
17

DataFrameの値を更新するときは、df.loc[...] = ...を使いましょう。

df.loc[10, "Age"] = 18
df
NameAge
10Alice18
20Bob24

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

コメント

タイトルとURLをコピーしました