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]
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
Pythonのスキルを使って毎月の収入源を増やすのが最適なんじゃないかという件
実際、今のスキルに合わせて仕事を獲得し、スキマ時間で毎月+5、+20、+70万円くらいの人が多いです。
必要なスキル、仕事の獲得までの流れは以下の記事で徹底解説しています。
(もちろん全部無料です)
空いた時間にぜひ参考にしてみてください。
まとめ
PandasフレームワークのDataFrameで特定の行を行番号・またはインデックス名を指定して取得する方法を整理しました。