pandas を利用してデータセットの可視化を素早く試行する

今まで [pandas](http://pandas.pydata.org/) + [matplotlib](http://matplotlib.org/) を利用したプロッティングとしては [pandas + matplotlib による多彩なデータプロッティング](http://qiita.com/ynakayama/items/68eff3cb146181329b48) や [matplotlib (+ pandas) によるデータ可視化の方法](http://qiita.com/ynakayama/items/2ec380ab1176e4569ebe) といったものを紹介してきました。

[抽出](http://qiita.com/ynakayama/items/1494cf4fdf988e1c7c7c)および[加工](http://qiita.com/ynakayama/items/cc8d19eb7d33b1e28b3e)したデータを俯瞰するにあたり、可視化までの流れをあらためて整理して追ってみましょう。

## データセットを pandas オブジェクトにする

まず pandas の世界にデータセットを持ってくることになりますが、これは主に 2 通りの流れがあります。

1. csv ファイルなど外部ファイルから pd.read_csv や pd.read_table といった関数を使って読み込む方法
2. 連想配列 (辞書) オブジェクトなどを DataFrame に変換する方法

このうち 1. についてはすでにそのまま使える構造化されたデータが外部のファイルにあるようなときに使います。たとえば iris.csv というファイルがあった場合に次のようにして pandas オブジェクトにします。

```py3
df = pd.read_csv("iris.csv")
```

また 2. については、ある程度 Python のコードで抽出や加工をしたときに生成したデータを pandas で扱いたいときに使います。 pandas には[充実したドキュメントがある](http://pandas.pydata.org/pandas-docs/stable/dsintro.html)のでこれを参照すると良いでしょう。 from_dict 関数は辞書オブジェクトをそのままデータフレームに変換します。またインデックスを明示的に指定したい場合は from_records 関数を利用すると便利です。

```py3
df = pd.DataFrame.from_records(my_dic, index=my_array)
```

### 転置行列を得る

データセットにおいて、しばしば X と Y の軸は観察者にとって逆の視点であることがあります。このようなときも pandas のデータフレームならば常に .T メソッドで簡単に[転置行列](http://ja.wikipedia.org/wiki/%E8%BB%A2%E7%BD%AE%E8%A1%8C%E5%88%97)を得ることができます。これは非常によく使うので憶えておくと良いでしょう。

```py3
dft = df.T
```

[pandas の教科書](http://shop.oreilly.com/product/0636920023784.do)では df = df.T としていることが多いようですが筆者は上のように非破壊的な変換を好みます。

## IPython で対話的にプロッティングする

matplotlib を使うコードを書くにしても試行錯誤が必要です。このとき [IPython](http://ipython.org/) 上で素早くデータフレームの図示を描画・確認するステップを繰り返すと効率的です。

ipython -i オプションは引数に Python スクリプトを指定することができ、このスクリプトを実行した状態でインタラクティブシェルを操作することができるようになります。これは大変便利です。

たとえば次のようにクラスがあったとします。

```py3
class MyClass:
    def __init__(self, args):
        self.my_var = args[1]
        self.my_array = []
        self.my_dic = {}

    def my_method(self):
        ...
```

ipython -i my_class.py としてシェルを起動すれば MyClass が読み込まれますから次のようにオブジェクトを取り出せます。

```py3
my_instance = MyClass()
arr = my_instance.my_array
dic = my_instance.my_dic
```

my_method で self.my_dic といったインスタンス変数にデータを格納していたなら、上のようにしてこのインスタンス変数からデータを取り出せますし、ここからプロッティングすれば対話的に可視化することができます。

## データフレームの代表的な可視化方法

そもそもデータフレームに変換できた時点でいつもの 2 次元のデータなのですから、ここまで説明すればやるべきことはある程度見えてきたと言っても良いでしょう。

まずよく試す可視化方法をいくつか紹介します。

データセットとしては有名な [Iris](http://archive.ics.uci.edu/ml/datasets/Iris) を利用します。

図形の詳細についてはすでに何度も紹介していますから、[過去の記事](http://qiita.com/ynakayama/items/68eff3cb146181329b48)を参照してください。

### 散布図行列

まずは定番の散布図行列です。

```py3
plt.figure() # キャンバスを用意

from pandas.tools.plotting import scatter_matrix
scatter_matrix(df) # 散布図行列を描く

plt.show() # 対話的に画像を表示する場合
plt.savefig("1.png") # 画像ファイルに出力する場合
```

![hoge2.png](https://qiita-image-store.s3.amazonaws.com/0/38501/b2c6dd06-007c-9559-6316-859ce23e7914.png)

これは各列と各行の相関を一気に俯瞰することができるスグレモノです。散布図行列を見ることで精神の安定をはかれるようになればだいぶ慣れたものですね。

### 単純なプロット

以降、キャンバスを用意するステップと画像を出力するステップは省きます。

```py3
df.plot(legend=True)
```

![hoge3.png](https://qiita-image-store.s3.amazonaws.com/0/38501/933298b7-9906-d3a0-546d-8d71cf939c35.png)

すでに何度も紹介した通り pandas では legend が既定で True になります。説明のせいで図がよく見えないという場合は legend=False にすれば良いです。

### 積み上げ棒グラフ

ためしにデータフレームの先頭 10 件をプロッティングするとこうなります。

```py3
df10 = df.head(10)
df10.plot(kind='barh', stacked=True, alpha=0.5, legend=True)
```

![1.png](https://qiita-image-store.s3.amazonaws.com/0/38501/423b8f8d-b512-acfd-d25a-c3622e72067a.png)

### 棒グラフ

1 次元のベクトル空間に絞りこんで可視化するなら棒グラフが便利です。

```py3
df['sepal width'].hist()
```

![hoge.png](https://qiita-image-store.s3.amazonaws.com/0/38501/19cf032e-4608-9e3c-e890-9e2099de6468.png)

### エリアチャート

時間ごとの経過における複数データの変化を追うときに便利です。

```py3
df.plot(kind='area', legend=True)
```

![3.png](https://qiita-image-store.s3.amazonaws.com/0/38501/c025165d-63c5-b5c3-0890-a6fcb8b2e60f.png)

## まとめ

いかがでしょう。次第に慣れてくると、データに向き合った際に無意識のうちにインタラクティブシェルを利用してプロッティングするようになるかと思います。試行錯誤がすばやく行える IPython と、シームレスに Python で使える pandas + matplotlib がいかに生産的なツールであるかその威力がよく理解できるかと思います。