MacでPython3環境をpyenvで作ってNetworkXのグラフを表示してみる

##前説

前に取り込んだ[Wikipediaのリンクデータ](http://qiita.com/grachro/items/11e59d16a929d27e274e)で、PythonのNetworkXを使ってネットワーク図を表示しようと思ったのですが、環境構築に手間取ったので手順を残します。ちなみにNetworkXは、先週出た[Python入門者の集い](http://python-nyumon.connpass.com/event/23466/)で知りました。


##Homebrewのインストール

非常に初歩的なところからで恐縮ですが、Mac用のパッケージ管理ツールの[Homebrew](http://brew.sh/)がインストールされているか、brewコマンドで確認します。

```bash
brew --version
```

まだインストールしていないようなら、Homebrewをインストールします。

```bash
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
/master/install)"
```
- [Homebrewの公式サイトの日本語ページ](http://brew.sh/index_ja.html)

インストールしていた場合は、最新版にアップデートます。

```bash
brew update
```

##pyenv-virtualenvの環境作成

###pyenv-virtualenvとは

Macには最初から2系のPythonが入ってますが、この環境を残しつつ、これからつくるプロジェクトは3系にしたいため、複数バージョンのPython環境を自動的に切り替えられるよう、[pyenv-virtualenv](https://github.com/yyuu/pyenv-virtualenv) をインストールします。

[pyenv](https://github.com/yyuu/pyenv)がPythonの複数環境切り替えツール（Simple Python version management ）
[virtualenv](https://pypi.python.org/pypi/virtualenv)がPython公式のPython仮想環境ビルダー（Virtual Python Environment builder）

らしいので、pyenv-virtualenvは、pyenvからvirtualenvを使うライブラリということでしょうか。
ともかくpyenv-virtualenvで、任意のディレクトリをPythonの2系と3系に自動的に切り替えられるようになります。

pyenvやpyenv-virtualenvの環境構築は、Qiitaに既にたくさん解説があります。

- [Macでpyenv+virtualenv](http://qiita.com/maosanhioro/items/47a52f96fefba7126f9b)
- [pyenvとvirtualenvで環境構築](http://qiita.com/Kodaira_/items/feadfef9add468e3a85b)
- [PyenvによるPython3.x環境構築(CentOS, Ubuntu)](http://qiita.com/akito1986/items/be5dcd1a502aaf22010b)
- [etc](http://qiita.com/tags/pyenv)
- [etc](http://qiita.com/tags/pyenv-virtualenv)

###pyenv-virtualenvのインストール

```bash
brew install pyenv-virtualenv
```

ちなみに、このインストールで、依存するpyenvも自動的にインストールされます。

```bash
$ brew install pyenv-virtualenv
==> Installing dependencies for pyenv-virtualenv: autoconf, pkg-config, openssl, readline, pyenv

```

###pyenv-virtualenvの設定

インストールが終わったら環境変数を設定

```bash:~/.bash_profile
export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
```

環境変数の変更を反映して、

```
source ~/.bash_profile
```

pyenvでインストール可能なバージョンを表示してみます。

```
pyenv install --list
```

リストからPython3系の最新バージョンを探してインストールします。

```bash
pyenv install 3.5.1
```

こんな感じでwww.python.orgからPythonがダウンロード＆インストールされます。

```bash
$ pyenv install 3.5.1
Downloading Python-3.5.1.tgz...
-> https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz
Installing Python-3.5.1...
```

終わったらまた環境変数の変更を反映。

```
source ~/.bash_profile
```

作業用ディレクトリに移動してそのディレクトリではPython3.5.1が動くようにします。

```bash
cd [Python3用の任意の作業ディレクトリ]
pyenv local 3.5.1
```

おわったら、環境が切り替わることを確認します。

```
$ cd ~
$ python --version
Python 2.7.10

$ cd [Python3用の任意の作業ディレクトリ]
$ python --version
Python 3.5.1
```

##pipのアップデート

これからNetworkXをインストールするのですが、インストールにはPythonのパッケージ管理システムのpipを使用します。Python3だとpipコマンドがディフォルトで付いてきますが、ディフォルトだと古いバージョンのようなのでアップデートしておきます。

```bash
cd [Python3用の任意の作業ディレクトリ]
pip install --upgrade pip
```

```bash
$ pip list
中略
pip (7.1.2)
中略

$ pip install --upgrade pip

$ pip list
中略
pip (8.0.2)
中略
```


##NetworkXのインストール

[NetworkX](https://networkx.github.io/)は、Pythonで複雑ネットワークを扱うためのライブラリです。
>NetworkX is a Python language software package for the creation, manipulation, and study of the structure, dynamics, and functions of complex networks.

```bash
cd [Python3用の任意の作業ディレクトリ]
pip install networkx
```

インストールが終わると.pyenv/versions/3.5.1以下にnetworkxのモジュールが配置されたようです。

```
$ ls ~/.pyenv/versions/3.5.1/lib/python3.5/site-packages/networkx
__init__.py		classes			drawing			generators		relabel.py		tests
__pycache__		convert.py		exception.py		linalg			release.py		utils
algorithms		convert_matrix.py	external		readwrite		testing			version.py

$ ls ~/.pyenv/versions/3.5.1/share/doc/networkx-1.11/examples
3d_drawing	advanced	algorithms	basic		drawing		graph		multigraph	pygraphviz
```

##NetworkXでコンソール表示をしてみる

試しに、NetrowkXのサイトに載っている[最初のサンプル](https://networkx.github.io/examples.html)を動かしてみます。

```py3:networkx-sample.py
import networkx as nx

G=nx.Graph()
G.add_node("spam")
G.add_edge(1,2)

print(G.nodes())
print(G.edges())
```

Python3に設定した環境にnetworkx-sample.pyスクリプトを作って実行します。

```bash
$ cd [Python3用の任意の作業ディレクトリ]
$ python networkx-sample.py 
['spam', 2, 1]
[(2, 1)]
```

ネットワークのノードとエッジがコンソール表示されました。


##matplotlibのインストール

次に公式サイトからネットワークをグラフィカルに表示している[サンプル](http://networkx.github.io/documentation/latest/examples/drawing/random_geometric_graph.html)を探して実行してみようと思いますが、グラフ表示には[matplotlib](http://matplotlib.org/)ライブラリが必要なようです。

またpipコマンドでインストールします。

```bash
pip install matplotlib
```

ここままサンプルを実行するとエラーになります。エラーメッセージが指しているのは[このページ](http://matplotlib.org/faq/virtualenv_faq.html)でしょうか？

```bash
RuntimeError: Python is not installed as a framework. The Mac OS X backend will not be able to function correctly if Python is not installed as a framework. 
See the Python documentation for more information on installing Python as a framework on Mac OS X. Please either reinstall Python as a framework, or try one of the other backends. 
If you are Working with Matplotlib in a virtual enviroment see 'Working with Matplotlib in Virtual environments' in the Matplotlib FAQ
```
（エラーメッセージは1行が長いので改行しています。）

書いてある通りにやっても解決しなかったので、Qiitaから解決方法を探します。
参考：[VirtualEnv環境でmatplotlibなどがimportできない](http://qiita.com/nnsnodnb/items/e8fc72ebe851b8c55a90)


matplotlibrcファイルを新規作成

```bash
~/.matplotlib/matplotlibrc
```

matplotlibrcに1行記述
>backend : TkAgg




##NetworkXでネットワーク図を表示をしてみる

公式サイトのサンプル[Random Geometric Graph](http://networkx.github.io/documentation/latest/examples/drawing/random_geometric_graph.html)をコピペしてPythonスクリプトを作成します。


```python:RandomGeometricGraph.py 
import networkx as nx
import matplotlib.pyplot as plt

G=nx.random_geometric_graph(200,0.125)
# position is stored as node attribute data for random_geometric_graph
pos=nx.get_node_attributes(G,'pos')

# find node near center (0.5,0.5)
dmin=1
ncenter=0
for n in pos:
    x,y=pos[n]
    d=(x-0.5)**2+(y-0.5)**2
    if d<dmin:
        ncenter=n
        dmin=d

# color by path length from node near center
p=nx.single_source_shortest_path_length(G,ncenter)

plt.figure(figsize=(8,8))
nx.draw_networkx_edges(G,pos,nodelist=[ncenter],alpha=0.4)
nx.draw_networkx_nodes(G,pos,nodelist=p.keys(),
                       node_size=80,
                       node_color=[float(v) for v in p.values()],
                       cmap=plt.cm.Reds_r)

plt.xlim(-0.05,1.05)
plt.ylim(-0.05,1.05)
plt.axis('off')
plt.savefig('random_geometric_graph.png')
plt.show()
```

そのままだとPython3で動かなかったので、1行変更しています。

original
>node_color=p.values()

こう変えました。多分2系と3系の違いなのだと思いますが、matplotlibのバージョンが原因かもしれません。
>node_color=[float(v) for v in p.values()]


###サンプルを実行

サンプルを実行すると何やらネットワーク図が表示されて、random_geometric_graph.pngファイルが作成されました。

```bash
python RandomGeometricGraph.py
```

![スクリーンショット 2016-02-01 14.38.15.png](https://qiita-image-store.s3.amazonaws.com/0/88743/c5f0df2d-f568-ba84-0837-53ef9e723585.png)