YutaKaのPython教室

Python の文法やライブラリ、API、環境構築について画像・動画・ソースコード付きで徹底解説!

pandas インデックスの基本操作|基本からデータ整理の便利技まで!

pandasDataFrameでは、インデックス名やカラム名を使ってデータにアクセスしますね。

とは言っても、pandasの操作に慣れていないうちは、ちょっとしたインデックス操作も難しいですよね。例えばこんな疑問も…。

  • そもそもインデックスはどういう仕組みになの?
  • 並べかえたり、最大値・最小値を見つけたりすることってできるの?

そこで、この記事では次の内容をサンプルコード付きで解説していきます:

  • インデックスの基本構造、インデックス内要素へのアクセス方法
  • 基本的なインデックス操作:データ探索、並べ替え、重複処理、欠損値処理

インデックスの基本操作をマスターして、自由にpandasを操作できるようになりましょう!

 

この記事ではインデックスの基本操作について解説しています。

インデックスへのラベルの設定(再設定や一部変更含む)については次の記事を参考にしてください。

≫pandas インデックス名の設定・変更|パターン別にわかりやすく解説
≫pandas インデックス名の設定・変更|パターン別にわかりやすく解説
pandasのDataFrameでは、インデックス名やカラム名を使ってデータにアクセスしますね。しかし、インデックスやコラムの操作は少しわかりにくい部分も…。そこで、この記事では①インデックスの基本的な設定方法、変更方法、②インデックス番号のリセット方法をサンプルコード付きでわかりやすく解説!
www.yutaka-note.com/entry/pandas_index_setting
 

インデックス、カラムの基本構造

そもそもインデックスやカラムとは、どういったものなのでしょうか?

まずはインデックスの正体についても解説していきます!

そもそもインデックスとカラムはどっちがどっち?

まずDataFrameのインデックスやカラムについて整理しましょう。

インデックス、カラムはそれぞれDataFrameの次の要素です。

  • インデックス:縦方向のラベル
  • カラム:横方向のラベル

DataFrameのインデックスやカラムは、表で言うところの行や列のタイトルのようなものですね。

次の図のように、インデックスやカラムには名前を付けることも可能です。

概要がわかったところで、次にインデックスやカラムの構造をもっと詳しく見ていきましょう。

インデックスの正体とは?!

実は、インデックスやカラムの正体はpd.Index系列のオブジェクトです。

インデックスを横向きにすればカラムになるので、カラムもpd.Index系列のオブジェクトで表現されます。

pd.Index系列のオブジェクトの代表例としては次のようなものがあります。

初めはpd.Indexの使い方を覚えて、必要に応じて他のオブジェクトの使い方も覚えていきたいですね。

pd.Index系列の例 説明
pd.Index いろいろなデータに対応する基本的なインデックス
pd.RangeIndex 連番に特化したインデックス
Ex) 0, 1, 2
pd.DatetimeIndex 日付、時刻に特化したインデックス
Ex) 2021-06-07, 2021-06-08
pd.MultiIndex 階層型インデックス
Ex) Apple 1, Apple 2, Banana 1, Banana 2など

まずはpd.Indexを例にインデックスの基本を理解しましょう。

pd.Index系列は次の2つの基本要素から構成されています。

  • インデックス名:インデックスやコラムのタイトルのようなもの
  • インデックスのデータ:個々のラベル名

例えば、次のようにDataFrameのインデックスやコラムにpd.Indexを設定可能です。

data = [[0, 1],
        [10, 11],
        [20, 21]]
 
df = pd.DataFrame(data, columns=pd.Index(["Data1", "Data2"]))
df.set_axis( pd.Index(['Name1', 'Name2', "Name3"], name="Names"), inplace=True)

以下では、インデックスの操作について解説しますが、元のオブジェクトは同じなのでカラムでもほぼ同等の操作が可能です。

インデックスの基本操作

インデックスの基本操作として、次の内容を解説します。

  • インデックス、カラムのオブジェクトを取得
  • インデックスの要素にアクセス
  • インデックス名にアクセス

インデックスのオブジェクトを取得|df.index

インデックスやカラムを操作するためには、まずはそれらのオブジェクトを取得する必要があります。

それぞれDataFrameの次の要素に対応しています。

  • インデックス:df.index
  • カラム:df.columns

print()関数で出力してみましょう。

data = [[0, 1],
        [10, 11],
        [20, 21]]
 
df = pd.DataFrame(data, columns=pd.Index(["Data1", "Data2"]))
df.set_axis( pd.Index(['Name1', 'Name2', "Name3"], name="Names"), inplace=True)
 
print(df.index)
# Index(['Name1', 'Name2', 'Name3'], dtype='object', name='Names')
 
print(df.columns)
# Index(['Data1', 'Data2'], dtype='object')

インデックス、カラムのpd.Indexオブジェクトの中身が表示されていますね。

各要素にアクセス|df.index[ ]

pythonのリストと同じように、インデックス番号でインデックスの各要素にアクセスできます。

サンプルコードでいくつかアクセスしてみましょう。

df.index[0]
# Name0
df.index[2]
# Name2
 
df.columns[1]
# Data1

スライスや負の値でのアクセスも可能です。

スライスの場合はpd.Indexオブジェクトで返されます。

df.index[0:2]
# Index(['Name0', 'Name1'], dtype='object', name='Names')

負の値で指定する場合も、リストと挙動は同じです。

df.index[-1]
# Name3

インデックス名にアクセス|df.index.name

pd.Indexname属性からインデックス名やカラム名にアクセスできます。

  • インデックス名:df.index.name
  • カラム名:df.columns.name

次のdfを例にインデックス名の表示、書き換え例を紹介します。

data = [[0, 1],
        [10, 11],]
 
df = pd.DataFrame(data, columns=pd.Index(["Data0", "Data1"]))
df.set_axis( pd.Index(['Name0', 'Name1'], name="Names"), inplace=True)

今は、インデックス名は"Names"になっていますね。

実際にdf.index.nameにアクセスして、インデックス名を表示してみましょう。

df.index.name
# Names

次にインデックス名を書き換えてみます。

df.index.name = "ind_name"

無事、インデックス名が変更できました。

pd.Indexrename()メソッドでインデックス名を変更することもできます。

df.index.rename("Ind_name", inplace=True)

インデックス内の検索

インデックス内のデータを検索する方法として、次の2つを紹介します。

  • ラベル名からインデックス番号を検索
  • 最大、最小値の検索

ラベル名からインデックス番号検索|df.index.get_loc

ラベル名に対応するインデックス番号を検索するには、get_loc()メソッドを使用します。

  • df.index.get_loc("検索するラベル名")|インデックス内のラベル位置を検索

"検索するラベル名"に対応するインデックス番号が返されます。

# df
#      c0  c1
# ind        
# i0    0   1
# i1   10  11
# i2   20  21
 
# インデックス内の"i2"を検索
df.index.get_loc("i2")
# 2
 
# カラム内の"c0"を検索
df.columns.get_loc("c0")
# 0
 
df.index.get_loc("i999")
# KeyError: 'i999'       

存在しないラベル名を検索するとKeyErrorになります。

最大・最小値の検索|df.index.max(), .argmax()

インデックスが数値の場合は、pd.Indexのメソッドで最大値、最小値の検索、それらのインデックス番号の検索が可能です。

メソッド一覧は次の通りです。

検索内容 最大値 最小値
最大・最小の値 df.index.max() df.index.min()
最大・最小値のインデックス番号 df.index.argmax() df.index.argmin()

カラムの最大・最小値を検索する場合には、df.indexの代わりにdf.cloumnsでカラムにアクセスします。

次のデータフレームを例に最大、最小値の検索例を紹介します。

data = [[10, 11, 12],
        [-10, -11, -22],
        [30, 31, 32],
        [20, 21, 22]]
 
df = pd.DataFrame(data, columns=["c0", "c1", "c2"]).set_index("c0")

このdfのインデックスの最大値、最小値とその位置を出力してみましょう。

# 最大値
print(f"インデックス内最大値:{df.index.max()}")
print(f"最大値のインデックス番号:{df.index.argmax()}")
# インデックス内最大値:30
# 最大値のインデックス番号:2
 
# 最小値
print(f"インデックス内最小値:{df.index.min()}")
print(f"最小値のインデックス番号:{df.index.argmin()}")
# インデックス内最小値:-10
# 最小値のインデックス番号:1

簡単ですね。

細かなメソッドの存在を知っているか知らないかだけがポイントですね。

インデックスの便利な操作

覚えておくと便利なインデックスの操作を3つ紹介します。

  • インデックスの並べ替え
  • 欠損値の検索、処理
  • 重複の検索、処理

インデックスの内容で並べ替え|df.sort_index()

DataFrameをインデックスの内容で昇順、降順に並べ替えるには、DataFrameのメソッドdf.sort_index()を使用します。

  • df.sort_index()dfをインデックスの内容で昇順、降順に並べ替え
引数名 説明
ascending 真偽値:True or False True(デフォルト):昇順 Ex) 1, 2, 3…A, B, C…
False:降順 Ex) 100, 99, 98…D, C, B…
inplace 真偽値:True or False Truedfそのものを上書き
False(デフォルト):新しいdfを返す(元のdfは変化なし)

次のDataFrameを例に昇順、降順の並べ替えを紹介します。

data = [[0, 1],
        [10, 11],
        [20, 21]]
 
df = pd.DataFrame(data, columns=["Data0", "Data1"])
df.index= pd.Index(['Banana', 'Apple', "Carotte"], name='Item')

インデックスの内容で昇順に並べ替えてみます。

df.sort_index(inplace=True)

次にascending = False を指定して、降順に並べ替えます。

df.sort_index(ascending=False, inplace=True)

欠損値の検索、処理

インデックス内の欠損値の検索、処理に関して次の内容を紹介します。

内容 dfの属性 or メソッド 出力
インデックスに欠損値があるか判定 df.index.hasnans 真偽値:True or False
        各要素が欠損値か真偽値で出力 df.index.isna() 真偽値の配列:
欠損値の位置がTrue、それ以外はFalse
欠損値の行を除去 df.index.dropna() 欠損値を除去したpd.Index
欠損値を他の値で置き換え df.index.fillna("代入値") 欠損値に値代入後のpd.Index

次のDataFrameを例にそれぞれの使い方を見ていきましょう。

data = [[0, 1],
        [10, 11],
        [20, 21],
        [30, 31]]
 
df = pd.DataFrame(data, columns=["c0", "c1"])
df.index= pd.Index(['i0', None, "i2", None], name='ind')

①インデックスに欠損値があるか判定df.index.hasnans

DataFrameのインデックスに一つでもNoneがあると、Trueを返します。

#      c0  c1
# ind        
# i0    0   1
# NaN  10  11
# i2   20  21
# NaN  30  31
 
df.index.hasnans
# True

シンプルですが、欠損値があるかないかだけを知りたいときは便利です。

②各インデックス要素が欠損値か真偽値で出力df.index.isna()

インデックス内の各データが欠損値かどうかを、真偽値配列で返します。

#      c0  c1
# ind        
# i0    0   1
# NaN  10  11
# i2   20  21
# NaN  30  31
 
df.index.isna()
# array([False,  True, False,  True])

真偽値の配列で返ってくることがポイントです。

df.loc[]で、DataFrameの一部を切り出せる機能と組み合わせると、DataFrameを抽出できます。

df.loc[df.index.isna()]で、インデックスが欠損値の行を抽出できます。

df.loc[ df.index.isna() ]
 
#      c0  c1
# ind        
# NaN  10  11
# NaN  30  31

③欠損値の行を除去df.index.dropna()

df.index.dropna()を使用すると欠損値を除去したpd.Indexを生成されます。

これをdf.loc[]に渡すことでも、インデックスが欠損値でない行を抽出することができます。

# 欠損値を除去したインデックスを生成
df.index.dropna()
# Index(['i0', 'i2'], dtype='object', name='ind')
 
# インデックスが欠損値でない行を抽出
df.loc[df.index.dropna()]
#      c0  c1
# ind        
# i0    0   1
# i2   20  21

④欠損値を他の値で置き換えdf.index.fillna("代入値")

df.index.fillna("代入値")で、インデックス内の欠損値を"代入値"に置き換えたpd.Indexを生成できます。

これで既存のインデックスdf.indexを上書きすれば、欠損値が"代入値"で置き換わります。

df.index = df.index.fillna("i_nan")
 
#        c0  c1
# ind          
# i0      0   1
# i_nan  10  11
# i2     20  21
# i_nan  30  31

欠損値が複数ある場合には、インデックスの重複が生じてしまいますね。

重複検索、処理

インデックス内の重複値の検索、処理に関して次の内容を紹介します。

内容 dfの属性 or メソッド 出力
インデックスに重複値があるか判定 df.index.has_duplicates 真偽値:True or False
インデックスが重複無しか判定 df.index.is_unique 真偽値:True or False
各要素が重複値か真偽値で出力 df.index.duplicated() 真偽値の配列:
重複値の位置がTrue、それ以外はFalse
重複値の行を除去 ~df.index.duplicated()
(これをdf.loc[]に渡す)
真偽値の配列:
重複値の位置がFalse、それ以外はTrue

次のDataFrameを例にそれぞれの使い方を見ていきましょう。

data = [[0, 1],
        [10, 11],
        [20, 21],
        [30, 31]]
 
df = pd.DataFrame(data, columns=["c0", "c1"])
df.index= pd.Index(['i0', "i_dup", "i2", "i_dup"], name='ind')

①インデックスに重複値があるか判定df.index.has_duplicates

DataFrameのインデックスに重複値が一つでもあると、Trueを返します。

#        c0  c1
# ind          
# i0      0   1
# i_dup  10  11
# i2     20  21
# i_dup  30  31
 
df.index.has_duplicates
# True

シンプルですが、重複があるかないかだけを知りたいときは便利です。

②インデックスがユニーク(重複無し)か判定df.index.is_unique

インデックスがユニークかの判定は、df.index.is_uniqueで可能です。

df.index.is_unique
# False

df.index.has_duplicatesの否定ですね。

③各インデックス要素が重複値か真偽値で出力df.index.duplicated()

インデックス内の各データが重複値かどうかを、真偽値配列で返します。

重複値の位置はTrueで表現されます。

デフォルトでは重複値のうち、一つ目の位置にはFalseが格納されて、二つ目以降が重複値として扱われます。

引数によって、重複値のうち最後の位置にFalseを格納させたり、重複値全ての位置にTrueを設定させたりできます。

説明
"first"(デフォルト) 一つ目を除いた重複値位置をTrueにする
"last" 最後のものを除いた重複値位置をTrueにする
False 全部の重複値位置をTrueにする

挙動の違いを具体的なサンプルコードで確認してみましょう。

#        c0  c1
# ind          
# i0      0   1
# i_dup  10  11  # ←重複値①の行
# i2     20  21
# i_dup  30  31  # ←重複値②の行
 
df.index.duplicated("first") # firstはデフォルト値なので省略可能
# [False False False True]
 
df.index.duplicated("last")
# [False True False False]
 
df.index.duplicated(False)
#[False  True False  True]

それぞれでTrueとして、重複値判定された位置が異なっていますね。

重複行のみ抽出したdfを生成したい場合には、df.loc[]df.index.duplicated()を渡します。

df.loc[df.index.duplicated(False)]
#        c0  c1
# ind          
# i_dup  10  11
# i_dup  30  31

④重複値の行を除去~df.index.duplicated()

インデックスの重複した行を除去したDataFrameを生成する場合には、~df.index.duplicated()df.loc[]に渡すのが最も簡単だと思います。

#        c0  c1
# ind          
# i0      0   1
# i_dup  10  11  # ←重複値①の行
# i2     20  21
# i_dup  30  31  # ←重複値②の行
 
df.loc[df.index.duplicated("first")] # firstはデフォルト値なので省略可能
#        c0  c1
# ind          
# i0      0   1
# i_dup  10  11 # ←重複値①の行
# i2     20  21
 
df.loc[~df.index.duplicated("last")]
#        c0  c1
# ind          
# i0      0   1
# i2     20  21
# i_dup  30  31 # ←重複値②の行
 
df.loc[~df.index.duplicated(False)]
#      c0  c1
# ind        
# i0    0   1
# i2   20  21

おわりに|padans関連おススメ追加コンテンツ

今回はpandasのインデックスの設定、変更に関する内容を紹介しました。

pandasは便利すぎて操作方法がわかりにくいことがよくあります…。

結局はコツコツ学ぶのが、pandasマスターの近道ですよね!≫【ブログカテゴリー:pandas】

≫【レビュー】「Pythonによるデータ分析入門」| pandas開発者によるpandasユーザーのためのpandasの教科書!
≫【レビュー】「Pythonによるデータ分析入門」| pandas開発者によるpandasユーザーのためのpandasの教科書!
「Pythonによるデータ分析入門」を、最初から最後まで実際に実践してみたレビューです。具体的にどのようなことができるようになったかを実例付きで紹介します!・DataFrameの生成方法・欠損値の処理方法・グラフ化の方法気になる学習時間は…?
www.yutaka-note.com/entry/2019/12/07/230219
 
≫pandas リストからDataFrameを生成|インデックスとコラムの設定も!
≫pandas リストからDataFrameを生成|インデックスとコラムの設定も!
pandasでは、リストからデータフレームを生成することもできます。しかし、pandasの操作に慣れていないうちは、ちょっとした操作も難しいですよね。この記事では、①リストからデータフレームを生成、行と列を追加する方法、②インデックス名、コラム名を設定する方法、③DataFrameを転値する方法(行と列が期待と逆だった時の対応)をサンプルコード付きで紹介!
www.yutaka-note.com/entry/pandas_list
 
≫pandas 辞書型からDataFrameを生成|インデックスとコラムの設定も!
≫pandas 辞書型からDataFrameを生成|インデックスとコラムの設定も!
pandasでは、辞書型からデータフレームを生成することもできます。しかし、pandasの操作に慣れていないうちは、ちょっとした操作も難しいですよね。この記事では、①辞書型からデータフレームを生成する方法、②辞書のキーをインデックス名、コラム名それぞれに設定する方法、③DataFrame()とDataFrame.from_dict()の違いをサンプルコード付きで紹介!
www.yutaka-note.com/entry/pandas_dict
 
≫pandas インデックス名の設定・変更|パターン別にわかりやすく解説
≫pandas インデックス名の設定・変更|パターン別にわかりやすく解説
pandasのDataFrameでは、インデックス名やカラム名を使ってデータにアクセスしますね。しかし、インデックスやコラムの操作は少しわかりにくい部分も…。そこで、この記事では①インデックスの基本的な設定方法、変更方法、②インデックス番号のリセット方法をサンプルコード付きでわかりやすく解説!
www.yutaka-note.com/entry/pandas_index_setting
 
≫pandas | read_excel() 図解でわかりやすく解説!
≫pandas | read_excel() 図解でわかりやすく解説!
pandasで、excelファイルを読み込むための関数read_excel()について、図解で徹底解説!①表のデータがセルA1から始まっていないときの対応方法②indexやlabelの行や列を指定する方法
www.yutaka-note.com/entry/pandas_read_excel_1
 
≫pandas | read_csv() 図解でわかりやすく解説!
≫pandas | read_csv() 図解でわかりやすく解説!
pandasでcsvファイルを読み込むための関数read_csv()について、図解で徹底解説! ①区切り文字の指定②indexやlabelの行や列を指定する方法③読み込む行・列の指定など細かい設定についての解説記事です!
www.yutaka-note.com/entry/pandas_read_csv
 
≫【レビュー】「Python実践データ分析100本ノック」|100本終えたらpandasが好きになっていた
≫【レビュー】「Python実践データ分析100本ノック」|100本終えたらpandasが好きになっていた
Python実践データ分析100本ノックで、実際に100本終了したレビューです。pythonでのデータ分析の入門書としてかなりの良書だったと思います。・python2~3冊目に何を勉強しようか迷っている人・時間をかけずにデータ分析の基本を学びたい人・pandasへの抵抗を減らしたい人
www.yutaka-note.com/entry/nock_100
 
≫pandas|head(), tail()でデータ先頭, 末尾を抽出!
≫pandas|head(), tail()でデータ先頭, 末尾を抽出!
pandasのDataFrameやSeriesで先頭や末尾の数行をさっと確認したい場合には、head()、tail()メソッドを使用します。引数で表示する行数を指定することもできますので、その使用方法を解説していきます。
www.yutaka-note.com/entry/pandas_head_tail
 

Twitter@YutaKaでは、ほぼ毎日pythonに関する情報を発信しています。

気楽にツイートしているので、気軽にフォローしてください!