Python Tech

pandas.DataFrameの行をインデックス指定で取得するときの方法とエラー対処

2021年5月6日

pandas.DataFrameでは行・列の値を柔軟な方法で取り出すことができます。

ですが柔軟性があることは難易度の高さにも繋がります。

実際、DataFrameから任意の位置にある値を取り出す方法はいくつもあり、それぞれ少しずつ仕様が異なっていたりします。

この記事では、特に「行」の取り出しに「インデックス名または行番号」を指定してアクセスする方法とそのエラー対処について整理しています。

 

ValueError: -1 is not in range エラーの原因と対策

以下のようなエラーがでたとき

ValueError: -1 is not in range
KeyError: -1

任意の行を取り出したいなら、行の指定方法が誤っているようです。

例えば、以下のようにしても行は取り出せません。

last_item = df[-1] # 取り出せない

行番号を指定して任意の行を取得するには ilocを使用します。

row = df.iloc[行番号]

例えば、最終行を取り出すなら以下のようにします。

これで最後の行のSeriesを取得できます。

last_item = df.iloc[-1]

最終行を取り出すならスライスではなくilocを使うようにしましょう。

 

インデックス(行名)または行番号でアクセスする方法まとめ

pandas DataFrameの行の取り出し方にはいろいろな方法があり、初心者ほど混乱する部分があります。ついでにここで行の取り出し方について整理しておきましょう。

今回の記事では、indexや行の位置を指定することで行を取り出す方法を整理します。

任意の「列」の値を指定して行を検索するやり方はまた別の方法になるので、注意が必要です。

確認環境:Python 3.9, Pandas 1.2.3

サンプルデータとして以下のDataFrameを用意しておきます。

dic_data = {
    'id': ['A1', 'B1', 'C1'],
    'name': ['Alpha', 'Beta', 'Charlie'],
}
df = pd.DataFrame(dic_data)
df.set_index('id', inplace=True)

#        name
# id         
# A1    Alpha
# B1     Beta
# C1  Charlie

 

[]スライスで指定する方法

カッコ内に行番号またはインデックス名のスライスを指定する方法です。

必ずスライス [start:stop] のかたちで書きます。単独の数値([1]や[2])では指定できません。

どちらも戻り値はpandas.DataFrameです。

# スライスで行番号を指定した抽出方法
df_flag = df[1:3]  # 行番号で1〜2の行を取得。3は含まれないことに注意
print(df_flag)

#        name
# id         
# B1     Beta
# C1  Charlie
# スライスで行名を指定した抽出方法
df_flag = df['B1':'C1'] # 行名B1〜C1の行を取得。この場合は'C1'も含まれる
print(df_flag)

#        name
# id         
# B1     Beta
# C1  Charlie

 

細かいところを確認しておきましょう。

上の書き方だと、行番号で指定してもインデックス名で指定しても同じ結果となりました。

ただし行番号の方では[1:3]としていて、存在しない4番目の要素をレンジの後ろに指定していますね。これは、後ろ(stop)で指定した番号の一つ前までを取り出す仕様だからです。
(list型などでスライスを作るときと同様です)

一方、インデックス名(行名)のスライス指定では、レンジの後ろ(stop)で指定した要素も含まれることになります。この違いは慣れるまでややこしいですよね。

理解しやすいコードを書くなら、後で説明するiloc, locを使用したほうがよいでしょう。

 

取得する範囲
df[start:stop]

startからstop – 1

df[‘start_name’:’stop_name’]

‘start_name’から’stop_name’

※stop_nameも含む

 

ちなみにindexのスライス指定は、int型の整数だけでなく、文字列や日時(datetime型)など様々なtypeに対応しています。

例えば、indexが日付のとき(datetimeIndex)のときは、以下のような感じで日付範囲を指定してスライスを取り出せます。

since = datetime.date(2021, 1, 1)
until = datetime.date(2021, 1, 2)
df_flag = df_date[since:until]

doc(英語)

 

loc, ilocで指定する方法

こちらも行名、または行番号で特定の行を取得する方法です。

loc、ilocはあらゆる範囲のデータを柔軟に取り出すための仕組みです。

locでは、行名・列名を指定して、特定の位置の任意のデータを抽出できます。

val = df.loc['A1', 'name']
print(val)
# Alpha

ilocは行番号・列番号を指定して、同じように特定の位置の値を取り出します。

val = df.iloc[0, 0]
print(val)
# Alpha

行を取り出すには、列を指定しないだけでOKです。

locは行名を指定、ilocは行番号を指定することで、行を取り出します。

row = df.loc['A1']
row = df.iloc[0]
print(row)
# name    Alpha
# Name: A1, dtype: object

取り出されるのが1行だけなので、この場合は Seriesが返ってきます。

また、loc、ilocでもスライスで行を指定できます。

df_flag = df.loc['B1':'C1']
print(df_flag)

#        name
# id         
# B1     Beta
# C1  Charlie
df_flag = df.iloc[1:3]
print(df_flag)

#       name
# id         
# B1     Beta
# C1  Charlie

 

まとめ

PandasフレームワークのDataFrameで特定の行を行番号・またはインデックス名を指定して取得する方法を整理しました。

  • この記事を書いた人

次世代ペンギン

長いのでペンギンとお呼びください。システム開発・プログラミングのお仕事をしています。甘味とコーヒーは生命線。日常での学びを記事にしています。

人気の記事

1

キャリアアップのため、または高収入を目指して、しっかりプログラミングを学びたいという人が増えてきましたね。 この記事では現役のエンジニアである私が、実際に仕事で稼げるようになるためのスクール選びで失敗 ...

2

先日の記事では、初心者からフリーランスプログラマーになる難しさと、それでもなんとか稼げるようになるにはどうしたらいいか解説しました。 今回の記事では、稼げるフリーランサーになるために必要な要素を、もう ...

3

気休めだけの甘い言葉は書きません。 最近は多くの企業やサイトで、使い捨てられるプログラマーが欲しいがために、甘い言葉で初心者プログラマを誘い出しています。 この記事では、まずは「現実」をちゃんと理解し ...

4

Vuetifyの v-progress-circular コンポーネントは、数値データや処理状況を環状(円状)のデザインで教えてくれるUIデザインです。 ローディングのスピナー(処理中のマーク)として ...

5

※画像はずとまよの新曲とは一切関係ありません   ずっと真夜中でいいのに。(以下、ずとまよ)の新曲『勘ぐれい』のMVが12月1日に公開されましたね。 MV前に公開されていた原曲を聴き、神曲な ...

6

Vuexのstore(ストア)を使うと、各コンポーネント間で個別にデータのやり取りすることなく、データを一元的に管理できます。Vueでは欠かせない機能といえるでしょう。 state(変数、コンポーネン ...

-Python, Tech
-, ,

© 2021 ペンギンのーと