DataFrameオブジェクトで特定の行や列、要素を選択するには幾つかの方法があります。
操作 | 方法 | 例 |
---|---|---|
列の選択 | ブラケット「[]」に列を指定 | df['col0']/df[0] |
整数の列ラベルによる列の選択 | iloc属性の第2引数に選択する列を指定(整数または整数のスライス) | df.iloc[:, 0]/df.iloc[:, 0:2] |
文字列の列ラベルによる列の選択 | loc属性の第2引数に選択する列を指定(列ラベルあるいは列ラベルを用いたスライス) | df.loc[:, 'col0']/df.loc[:, 'col0':'col1'] |
整数インデックスによる行の選択 | iloc属性に行を指定 | df.iloc[0] |
行ラベルによる行の選択 | loc属性に行を指定 | df.loc['row0'] |
複数行の選択 | ブラケット「[]」に行のスライスを指定 | df['col0':'col1']/df[0:1] |
ブーリアン値による複数行の選択 | ブラケットにブーリアン値を要素とするリストを指定 | df[[True, False]] |
整数の軸ラベルによる要素の選択 | iloc属性に選択する行と列を指定 | df.iloc[0, 0]/df.iloc[0:2, 0:2] |
文字列の軸ラベルによる要素の選択 | loc属性に選択する行と列を指定 | df.loc['row0', 'col0']/df.loc['row0':'row1', 'col0':'col1'] |
DataFrameオブジェクトの行や列、要素を選択する方法 |
この他にもat属性やiat属性を使用して特定の要素を1つだけ選択することも可能ですが、今回は主にloc属性やiloc属性を使う方法を紹介します。
以下では幾つかの例を見ていきましょう。ここでは次のようにindexパラメーターとcolumnsパラメーターの両者を指定したDataFrameオブジェクトと、どちらも指定していないDataFrameオブジェクトを生成して、その動作を確認してみます。
df = pd.DataFrame([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
df2 = pd.DataFrame([[0, 1, 2], [3, 4, 5], [6, 7, 8]],
index=['row0', 'row1', 'row2'],
columns=['col0', 'col1', 'col2'])
print(df)
# 出力結果:
# 0 1 2
#0 0 1 2
#1 3 4 5
#2 6 7 8
print(df2)
# 出力結果:
# col0 col1 col2
#row0 0 1 2
#row1 3 4 5
#row2 6 7 8
列を選択する一番簡単な方法はブラケット「[]」に対象の列を指定することです。
# 整数の列ラベルを指定して列を選択
print(df[0])
# 出力結果:
#0 0
#1 3
#2 6
#Name: 0, dtype: int64
# 文字列の列ラベルを指定して列を選択
print(df2['col0'])
# 出力結果:
#row0 0
#row1 3
#row2 6
#Name: col0, dtype: int64
dfオブジェクトは作成時にcolumnsパラメーターを指定していないので、最初の例では整数の列ラベルを指定しています。次の例ではdf2オブジェクトは作成時にcolumnsパラメーターを指定しているので、ブラケット内に文字列の列ラベルを指定しています。
逆にdfオブジェクトに文字列の列ラベルを指定しようとしてもこれが無理なことは容易に想像できます('col0'といわれてもどれが対応する列かが分かりません)。でも、df2オブジェクトに整数の軸ラベルを指定できそうな気もします。試してみるとどうでしょう。
print(df2[0])
すると、次のようにKeyError例外が発生します。
というわけで、整数以外の列ラベルを持つDataFrameオブジェクトについては、ブラケットを使って列を選択する際には整数は指定できないことが分かりました。
次にiloc属性とloc属性を使った例を紹介しましょう。iloc属性は整数の軸ラベルを用いて特定の行や列、要素を選択するために、loc属性は整数以外(文字列などの)軸ラベルを用いて特定の行や列、要素を選択するために使います(ただし、index/columnsパラメーターを指定せずに作成したDataFrameオブジェクトについては整数の軸ラベルをloc属性に渡すことも可能です)。
これらを使って列を選択するときには「オブジェクト.iloc[行指定, 列指定]」または「オブジェクト.loc[行指定, 列指定]」のような形で指定します(実際には多くの指定方法があります。これについてはpandasのドキュメント「pandas.DataFrame.iloc」や「pandas.DataFrame.loc」を参照してください)。
「行指定」と「列指定」にはPythonのスライス表記を用いることで、複数の行や列を選択することも可能です。が、まずは行指定には単独のコロン「:」だけを指定して(全ての行を選択)、列の扱いだけを見てみます。
print(df.iloc[:, 1])
# 出力結果:
#0 1
#1 4
#2 7
#Name: 1, dtype: int64
print(df2.loc[:, 'col1'])
# 出力結果:
#row0 1
#row1 4
#row2 7
#Name: col1, dtype: int64
上の2つの例では2つのDataFrameオブジェクトの同じ列(第1列)を選択しています。気を付けたいのは、df2オブジェクトは文字列の列ラベルを持っていますが、だからといってiloc属性に整数値を指定できないわけではない点です。そして、dfオブジェクトには文字列の列ラベルを付与していませんが、その場合は上でも述べたように整数値をloc属性に指定できる点にも注意してください。
print(df.loc[:, 1]) # 文字列の列ラベルがないので、loc属性に整数値を指定可能
# 出力結果:
#0 1
#1 4
#2 7
#Name: 1, dtype: int64
print(df2.iloc[:, 1]) # 文字列の列ラベルがあっても、iloc属性を使用可能
# 出力結果:
#row0 1
#row1 4
#row2 7
#Name: col1, dtype: int64
iloc属性とloc属性の振る舞いをまとめると次のようになります。
「文字列など、整数値以外の軸ラベル」と書いているのは、整数を要素とするタプルなどを軸ラベルとして設定することも可能だからです(何らかの理由で機械的に軸ラベルを生成するのであれば、そのような方法もありでしょう)。
なお、行指定や列指定にはスライスも指定可能です。ただし、loc属性は動作がPythonのスライスと異なる点には注意してください。以下に例を示します。
print(df2.loc[:, 'col0':'col2'])
# 出力結果:
# col0 col1 col2
#row0 0 1 2
#row1 3 4 5
#row2 6 7 8
Pythonのスライスで「開始:終了」と指定したときには、「終了」に指定した位置の要素は含まれません。しかし、この例では「'col0':'col2'」 というスライスを指定しているにもかかわらず、'col2'列の内容も選択されています。恐らく、これは文字列の列ラベルを使う場合、末尾列(あるいは末尾行)を意味する「-1」に相当する指定ができないからでしょう。
そのため、文字列の列ラベルを持たないDataFrameオブジェクト(ここではdfオブジェクト)でloc属性を使う場合とiloc属性を使う場合とで、その結果も異なります。
print(df.iloc[:, 0:2])
# 出力結果:
# 0 1
#0 0 1
#1 3 4
#2 6 7
print(df.loc[:, 0:2])
# 出力結果:
# 0 1 2
#0 0 1 2
#1 3 4 5
#2 6 7 8
iloc属性やloc属性を使うときには、こうした点に注意してください。
列の選択では「DataFrameオブジェクト[列ラベル]」のような形で特定の行を選択できました。が、単一行を選択するにはどうすればよいでしょう。実はこれと似た形で単一行を選択はできません。ただし、ブラケットに行ラベルをスライス形式で記述することで、複数行を選択することは可能です。以下に例を示します。
print(df[0:2])
# 出力結果:
# 0 1 2
#0 0 1 2
#1 3 4 5
print(df2['row0':'row2'])
# 出力結果:
# col0 col1 col2
#row0 0 1 2
#row1 3 4 5
#row2 6 7 8
ということは「df[0:1]」のように書けば単一行を選択することは可能でしょう(可能です)。筆者個人の感触ではブラケット内にラベルを1つ書くかスライスを書くかで、選択されるのが列になるか行になるかが変わるなんて「分かりづらいことしやがって」となるのですが、そういう仕様だからしょうがありません。覚えるようにしましょう。
もう一つ。上の2つ目の例を見れば分かる通り、行選択でのスライス表記でも文字列の行ラベルを使ったときには終了要素として選択したものは、選択範囲に含まれることは覚えておくようにしましょう(最初の例では「0:2」のように整数インデックスを使用しているので2行が選択されていますが、文字列の行ラベルでスライスを記述した2つ目の例では3行が選択されています)。
また、特定の行の全列を選択するにはiloc属性やloc属性で第1引数だけを指定します。以下に例を示します。
print(df.iloc[1])
# 出力結果:
#0 3
#1 4
#2 5
#Name: 1, dtype: int64
print(df2.loc['row1'])
# 出力結果:
#col0 3
#col1 4
#col2 5
#Name: row1, dtype: int64
この例はどちらもDataFrameオブジェクトの第1行を選択する例です。出力結果が縦に伸びているのでちょっと分かりにくいかもしれませんが、'col0'、'col1'、'col2'とあることから1行の内容が表示されていることを確認してください。
スライスを指定すれば複数行も選択できますが、例は省略してもよいでしょう。
iloc属性とloc属性で行と列を選択する方法を紹介してきましたが、これを組み合わせればDataFrameオブジェクトから特定の要素を選択できるのは既にお気付きでしょう。簡単に例を示します。
print(df.iloc[2, 2]) # 8
print(df2.loc['row2', 'col2']) # 8
これらはどちらも第2行の第2列の要素を選択する例です。よって、結果はもちろん8です。このように行指定と列指定にインデックスや列ラベルを単独で指定すれば特定の要素を1つだけ選択できます。
スライスを指定することで、複数の要素を選択できるのもすぐに分かるでしょう。
print(df.iloc[0:2, 0:2])
# 出力結果:
# 0 1
#0 0 1
#1 3 4
この例では第0行と第1行の第0列と第1列を選択するように指定しています。そのため、出力結果にあるように2次元のデータの左上の部分が選択されました。
最後に行や列、要素を選択したときに得られる結果のデータ型がどうなっているかを確認しておきましょう。といっても、答えは簡単で単一の行や列ならそれはSeriesオブジェクトになります。複数の行や列ならそれはDataFrameオブジェクトです。単一の要素であれば、その値のデータ型になります。複数要素を選択したときにそれが複数の行と列にまたがるのであれば、DataFrameオブジェクトが返されます。
実際にコードで確認してみましょう。
result = df2['col0'] # 単独列の選択
print(type(result)) # <class 'pandas.core.series.Series'>
result = df.iloc[:, 0] # 単独列の選択
print(type(result)) # <class 'pandas.core.series.Series'>
result = df.iloc[:, 0:2] # 複数列の選択
print(type(result)) # <class 'pandas.core.frame.DataFrame'>
result = df[0:2] # 複数行の選択
print(type(result)) # <class 'pandas.core.frame.DataFrame'>
result = df2.loc['row0', 'col0'] # 単独要素の選択
print(type(result)) # <class 'numpy.int64'>
result = df.loc[::2, ::2]
print(type(result)) # <class 'pandas.core.frame.DataFrame'>
今回はDataFrameオブジェクトの生成と、その行や列、個々の要素の選択について見ました。次回以降もDataFrameオブジェクトについてさらに詳しく見ていく予定です。
Copyright© Digital Advantage Corp. All Rights Reserved.