スライドショースライドショースライドショー

【Pandas入門】DataFrameにloc, ilocで要素アクセス!

こんにちは!インストラクターのフクロウです!PandasのDataFrameはデータをエクセルの表のように扱うことができて非常に便利です。

この記事では、DataFrameをより便利に使いために、DataFrameの特定の要素にアクセスする機能であるloc、ilocについて紹介します。Pandasは現在のデータ解析の現場においてマストなライブラリです!使い方を覚えて試してみてくださいね。

DataFrameの要素にアクセス

DataFrameやSeriesの要素にアクセスする機能は、以下の4つが用意されています。

  • loc
  • at
  • iloc
  • iat


それぞれ、loc, atは行や列の名前で要素へアクセスし、iがついているilocやiatは名前ではなくindex(NumPyの配列のように数字)でアクセスします。loc/ilocは複数要素をスライスすることができ、at/iatは一つの要素を取り出すことができます。

この記事ではloc、ilocに注目して解説していきます!

データの読み込み

まずはデータを読み込んでDataFrameを作りましょう。データセットはscikit-learnに収録されているiris datasetを使います。

In [1]:
import pandas as pd 
import numpy as np 
from sklearn.datasets import load_iris

In [2]:

iris = load_iris()
df = pd.DataFrame(data=iris.data, columns=iris.feature_names)
df["label"] = [iris.target_names[i] for i in iris.target]
df.head()

Out[2]:

sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa

DataFrameのサイズ確認をしてみましょう。

In [3]:
df.shape
Out[3]:
(150, 5)

locで行・列を名前で切り出す

DataFrameオブジェクトにはlocというインスタンス変数があります。locは行や列の名前を使って要素を切り出す操作を提供してくれます。

行の切り出し

まずは行の名前で取り出してみましょう。

In [4]:
# 0行目を取り出す 
df.loc[0]
Out[4]:
sepal length (cm)       5.1
sepal width (cm)        3.5
petal length (cm)       1.4
petal width (cm)        0.2
label                setosa
Name: 0, dtype: object
In [5]:
# 一行だけ取り出したときはSeries型になる 
type(df.loc[0])
Out[5]:
pandas.core.series.Series

In [6]:

# 1~4行目を取り出す
df.loc[1:4]

Out[6]:

sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
In [7]:
# 複数行取り出したときはDataFrame型になる 
type(df.loc[1:4])
Out[7]:
pandas.core.frame.DataFrame

行で取り出すのは簡単ですね。

一般的に行の名前は数字でインデックスがつけられているので、「名前でアクセス」しているっぽくないですね。

列の切り出し

では次に、列の名前で取り出してみましょう。

In [8]:
# "sepal length (cm)"列をすべて取り出す
df.loc[:,"sepal length (cm)"]
Out[8]:
0      5.1
1      4.9
2      4.7
3      4.6
4      5.0
5      5.4
6      4.6
7      5.0
8      4.4
9      4.9
10     5.4
      ... 
140    6.7
141    6.9
142    5.8
143    6.8
144    6.7
145    6.7
146    6.3
147    6.5
148    6.2
149    5.9
Name: sepal length (cm), Length: 150, dtype: float64

注意しなければならないのは、行を指定した後に列を指定しないと使えないという点です。このあたりはnp.arrayと同じスライス方法ですね。

In [9]:
# 行を指定せずに列だけを指定するとエラー 
df.loc["sepal length (cm)"]
[エラーメッセージ]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py in _validate_key(self, key, axis)
   1789                 if not ax.contains(key):
-> 1790                     error()
   1791             except TypeError as e:

/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py in error()
   1784                                .format(key=key,
-> 1785                                        axis=self.obj._get_axis_name(axis)))
   1786 

KeyError: 'the label [sepal length (cm)] is not in the [index]'

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
<ipython-input-9-007b3bdd281d> in <module>()
      1 # 行を指定せずに列だけを指定するとエラー
----> 2 df.loc["sepal length (cm)"]

/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py in __getitem__(self, key)
   1476 
   1477             maybe_callable = com._apply_if_callable(key, self.obj)
-> 1478             return self._getitem_axis(maybe_callable, axis=axis)
   1479 
   1480     def _is_scalar_access(self, key):

/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py in _getitem_axis(self, key, axis)
   1909 
   1910         # fall thru to straight lookup
-> 1911         self._validate_key(key, axis)
   1912         return self._get_label(key, axis=axis)
   1913 

/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py in _validate_key(self, key, axis)
   1796                 raise
   1797             except:
-> 1798                 error()
   1799 
   1800     def _is_scalar_access(self, key):

/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py in error()
   1783                 raise KeyError(u"the label [{key}] is not in the [{axis}]"
   1784                                .format(key=key,
-> 1785                                        axis=self.obj._get_axis_name(axis)))
   1786 
   1787             try:

KeyError: 'the label [sepal length (cm)] is not in the [index]'

行同様に複数列をスライスすることもできます。

このとき、カッコで囲んで切り出したい列名を列挙しましょう。

In [10]:
# "sepal length (cm)"、"petal length (cm)"列を0~9列取り出す 
df.loc[:9,["sepal length (cm)","petal length (cm)"]]

Out[10]:

sepal length (cm) petal length (cm)
0 5.1 1.4
1 4.9 1.4
2 4.7 1.3
3 4.6 1.5
4 5.0 1.4
5 5.4 1.7
6 4.6 1.4
7 5.0 1.5
8 4.4 1.4
9 4.9 1.5

ilocで行・列をindexで切り出す

locと同様に行や列を指定して要素を切りだすインスタンス変数がilocです。これはindexを使って要素を切り出すので、よりnp.arrayのように使うことができますよ!

行の切り出し

iris datasetのDataFrameでは、locの例と同じような操作になります。

In [11]:
# 10~14行目を取り出す 
df.iloc[10:15]

 

Out[11]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
10 5.4 3.7 1.5 0.2 setosa
11 4.8 3.4 1.6 0.2 setosa
12 4.8 3.0 1.4 0.1 setosa
13 4.3 3.0 1.1 0.1 setosa
14 5.8 4.0 1.2 0.2 setosa

列の切り出し

locの例では、列の名前を使っていましたね。ilocでは左から最初の列を0としたインデックスでアクセスします。

In [12]:
# 0~2列の100行目を切り出す 
df.iloc[100,0:2]
Out[12]:
sepal length (cm)    6.3
sepal width (cm)     3.3
Name: 100, dtype: object
In [13]:
# 3~4列の100~119行を切り出す 
df.iloc[100:120, 3:]

Out[13]:

petal width (cm) label
100 2.5 virginica
101 1.9 virginica
102 2.1 virginica
103 1.8 virginica
104 2.2 virginica
105 2.1 virginica
106 1.7 virginica
107 1.8 virginica
108 1.8 virginica
109 2.5 virginica
110 2.0 virginica
111 1.9 virginica
112 2.1 virginica
113 2.0 virginica
114 2.4 virginica
115 2.3 virginica
116 1.8 virginica
117 2.2 virginica
118 2.3 virginica
119 1.5 virginica

まとめ

この記事ではDataFrameをスライスする方法について紹介しました。DataFrameは今回説明に使ったような小規模のものだと扱いやすいのですが、実際の課題で扱うような大規模なものだと見通しが悪くなります。

もちろんエクセルのようなものにDataFrameを書き出すこともできますが、loc,ilocなどを使いこなせばPythonで処理を完結させることも簡単です。

前処理も可視化も結果の確認にも便利なPandasなので、このような操作をしっかり使いこなして恩恵を受けたいですね。

LINEで送る
Pocket

書いた人

フクロウ

フクロウ

第一言語はPythonです。
皆さんRustやりましょう。