note.nkmk.me

pandasのインデックス参照で行・列を選択し取得

Date: 2018-02-12 / tags: Python, pandas

pandas.DataFrame, pandas.Seriesのインデックス(添字)[]を指定することで、行・列または要素の値を選択し取得することができる。

pandas.DataFrameの場合、[]の中に指定する値のタイプによって以下のようなデータが取得できる。

  • [列名] : 単独の列をpandas.Seriesとして取得
  • [列名のリスト] : 複数列をpandas.DataFrameとして取得
  • [行名・行番号のスライス] : 単独または複数行をpandas.DataFrameとして取得

pandas.Seriesの場合は以下のようになる。

  • [行名・行番号] : 単独の要素の値をそれぞれの型で取得
  • [行名・行番号のリスト] : 複数の要素の値をpandas.Seriesとして取得
  • [行名・行番号のスライス] : 単独または複数の要素の値をpandas.Seriesとして取得

pandas.DataFrameで要素の値を抽出したり、列をスライス、行を行名・行番号やそのリストで選択したい場合はat, iat, loc, ilocを使う。以下の記事を参照。

今回のサンプルコードでは以下のcsvデータをread_csvで読み込んで使用する。

引数index_colで最初の列をindexとしている。

import pandas as pd

df = pd.read_csv('data/src/sample_pandas_normal.csv', index_col=0)
print(df)
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

既存のDataFrameの列をset_index()indexに指定することもできる。

スポンサーリンク

pandas.DataFrameの列を取得

[]に列名(列ラベル)を指定すると、選択した列が抽出されpandas.Seriesとして取得できる。

print(df['age'])
print(type(df['age']))
# name
# Alice      24
# Bob        42
# Charlie    18
# Dave       68
# Ellen      24
# Frank      30
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

attribute(属性)として.に続けて列名を指定することもできる。ただし、列名が既存のメソッド名などと被るとそちらが優先されるので注意が必要。

print(df.age)
print(type(df.age))
# name
# Alice      24
# Bob        42
# Charlie    18
# Dave       68
# Ellen      24
# Frank      30
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

列名のリストを指定すると、選択した複数列が抽出されpandas.DataFrameとして取得できる。

print(df[['age', 'point']])
print(type(df[['age', 'point']]))
#          age  point
# name               
# Alice     24     64
# Bob       42     92
# Charlie   18     70
# Dave      68     70
# Ellen     24     88
# Frank     30     57
# <class 'pandas.core.frame.DataFrame'>

スライスの場合は空のpandas.DataFrameとなって使えない。スライスは行の指定だと見なされるため(後述)。

print(df['age':'point'])
# Empty DataFrame
# Columns: [age, state, point]
# Index: []

locを用いると列のスライスも可能。またilocを用いると列名(列ラベル)ではなく列番号で指定することもできる。詳細は以下の記事を参照。

print(df.loc[:, 'age':'point'])
print(type(df.loc[:, 'age':'point']))
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57
# <class 'pandas.core.frame.DataFrame'>

print(df.iloc[:, [0, 2]])
print(type(df.iloc[:, [0, 2]]))
#          age  point
# name               
# Alice     24     64
# Bob       42     92
# Charlie   18     70
# Dave      68     70
# Ellen     24     88
# Frank     30     57
# <class 'pandas.core.frame.DataFrame'>

pandas.DataFrameの行を取得

[]にスライスを指定すると、該当範囲の複数行が抽出されpandas.DataFrameとして取得できる。

print(df[1:4])
print(type(df[1:4]))
#          age state  point
# name                     
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# <class 'pandas.core.frame.DataFrame'>

スライスなので、start:stop:stepのようにstepを指定することも可能。奇数行または偶数行を抽出して取得できる。

print(df[::2])
print(type(df[::2]))
#          age state  point
# name                     
# Alice     24    NY     64
# Charlie   18    CA     70
# Ellen     24    CA     88
# <class 'pandas.core.frame.DataFrame'>

print(df[1::2])
print(type(df[1::2]))
#        age state  point
# name                   
# Bob     42    CA     92
# Dave    68    TX     70
# Frank   30    NY     57
# <class 'pandas.core.frame.DataFrame'>

あくまでもスライスでないとダメで、行番号を単独で指定するとエラーとなる。

# print(df[1])
# KeyError

一行だけ選択される場合も、取得できるのはpandas.DataFramepandas.Seriesにはならない。

print(df[1:2])
print(type(df[1:2]))
#       age state  point
# name                  
# Bob    42    CA     92
# <class 'pandas.core.frame.DataFrame'>

行番号ではなく行名(行ラベル)でスライスを指定することもできる。行名(行ラベル)のスライスの場合はstopの行も選択される。

print(df['Bob':'Ellen'])
print(type(df['Bob':'Ellen']))
#          age state  point
# name                     
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# <class 'pandas.core.frame.DataFrame'>

locilocを用いると行に対して行名・行番号を単独で指定してpandas.Seriesとして取得したり、リストで複数行を選択したりできる。詳細は以下の記事を参照。

print(df.loc['Bob'])
print(type(df.loc['Bob']))
# age      42
# state    CA
# point    92
# Name: Bob, dtype: object
# <class 'pandas.core.series.Series'>

print(df.loc[['Bob', 'Ellen']])
print(type(df.loc[['Bob', 'Ellen']]))
#        age state  point
# name                   
# Bob     42    CA     92
# Ellen   24    CA     88
# <class 'pandas.core.frame.DataFrame'>

print(df.iloc[[1, 4]])
print(type(df.iloc[[1, 4]]))
#        age state  point
# name                   
# Bob     42    CA     92
# Ellen   24    CA     88
# <class 'pandas.core.frame.DataFrame'>

pandas.Seriesの値を取得

以下のpandas.Seriesを例とする。

s = df['age']
print(s)
# name
# Alice      24
# Bob        42
# Charlie    18
# Dave       68
# Ellen      24
# Frank      30
# Name: age, dtype: int64

行名・行番号の場合はその値、リストやスライスの場合は選択した複数の値をpandas.Seriesとして取得できる。リストやスライスの場合、一行だけが抽出されてもpandas.Series

行名(行ラベル)のスライスの場合はstopの行も選択される。

print(s[3])
# 68

print(s[[1, 3]])
print(type(s[[1, 3]]))
# name
# Bob     42
# Dave    68
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

print(s[1:3])
print(type(s[1:3]))
# name
# Bob        42
# Charlie    18
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

print(s[[1]])
print(type(s[[1]]))
# name
# Bob    42
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

print(s[1:2])
print(type(s[1:2]))
# name
# Bob    42
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

print(s['Dave'])
# 68

print(s[['Bob', 'Dave']])
print(type(s[['Bob', 'Dave']]))
# name
# Bob     42
# Dave    68
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

print(s['Bob':'Dave'])
print(type(s['Bob':'Dave']))
# name
# Bob        42
# Charlie    18
# Dave       68
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

print(s[['Bob']])
print(type(s[['Bob']]))
# name
# Bob    42
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

print(s['Bob':'Bob'])
print(type(s['Bob':'Bob']))
# name
# Bob    42
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

行名が整数値の場合、行名・行番号の指定が曖昧になるため、例えば最終行を示す-1を指定するとエラーになる。行名と行番号を明確に区別して指定するにはpandas.Seriesに対してもat, iat, loc, ilocを使う。

以下の記事を参照。

行名が文字列であれば-1でもエラーは発生しない。

s_i = s.reset_index(drop=True)
print(s_i)
# 0    24
# 1    42
# 2    18
# 3    68
# 4    24
# 5    30
# Name: age, dtype: int64

# print(s_i[-1])
# KeyError

print(s_i.iat[-1])
# 30

print(s[-1])
# 30

pandas.DataFrameの要素の値を取得

pandas.DataFrameからpandas.Seriesを抽出し、さらにそのpandas.Seriesから値を選択して取得することで、pandas.DataFrameから要素の値を取得できる。

print(df['age']['Alice'])
# 24

print(df.age[0])
# 24

スライスやリストを組み合わせて任意の範囲を抽出することもできる。

print(df['Bob':'Dave'][['age', 'point']])
print(type(df['Bob':'Dave'][['age', 'point']]))
#          age  point
# name               
# Bob       42     92
# Charlie   18     70
# Dave      68     70
# <class 'pandas.core.frame.DataFrame'>

at, iat, loc, ilocを使うともっと柔軟に位置や範囲を選択して抽出することが可能。以下の記事を参照。

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事