pythonでグラフを作ろう 第2回 -ファイルからデータを読み込んでプロット-

#はじめに
前回はpython内で生成したデータをプロットしました。しかし、実際は他の何らかの方法により生成されたデータ(例えば実験結果や数値計算結果)をプロットすることが多いです。今回は別のファイルからデータを読み込んでプロットする方法を解説します。

#データ読み込み&プロット
以下のようなデータが与えられているとします。まずは以下のデータを"sin.dat"というファイルに保存してください(空ファイルを生成して以下の内容をコピペすればOKです)。

```d
  -3.1415926535897931       -1.2246467991473532E-016
  -2.8274333882308138      -0.30901699437494751     
  -2.5132741228718345      -0.58778525229247325     
  -2.1991148575128552      -0.80901699437494745     
  -1.8849555921538759      -0.95105651629515364     
  -1.5707963267948966       -1.0000000000000000     
  -1.2566370614359172      -0.95105651629515353     
 -0.94247779607693793      -0.80901699437494745     
 -0.62831853071795862      -0.58778525229247314     
 -0.31415926535897931      -0.30901699437494740     
   0.0000000000000000        0.0000000000000000     
  0.31415926535897931       0.30901699437494740     
  0.62831853071795862       0.58778525229247314     
  0.94247779607693793       0.80901699437494745     
   1.2566370614359172       0.95105651629515353     
   1.5707963267948966        1.0000000000000000     
   1.8849555921538759       0.95105651629515364     
   2.1991148575128552       0.80901699437494745     
   2.5132741228718345       0.58778525229247325     
   2.8274333882308138       0.30901699437494751     
   3.1415926535897931        1.2246467991473532E-016
```

このデータをプロットするためのコードは以下の通りです。

```python
#############################################
####### begin import libraries ##############
import numpy as np
import matplotlib.pyplot as plt
####### end import libraries ###############
############################################

#############################################
####### begin read data #####################
DATA = np.loadtxt("./sin.dat")
x = DATA[:,0]
y = DATA[:,1]
####### end read data #######################
#############################################

#############################################
####### begin plot ##########################
plt.scatter(x,y)
plt.savefig("sin.png")
plt.show()
####### end plot ############################
#############################################
```
以下のような画像が生成されていればOKです。
![sin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1920250/b403a911-3869-ec24-41be-3a520180034d.png)

#解説
　2ブロック目について説明します。まずは**np.loadtxt**というnumpyの関数を用いてデータを読み取り、**DATA**という変数に格納しています。ここでDATAという変数は21行$\times$2列の変数です。次の2行でそれぞれの列の値を$x$と$y$へと格納しています。"x=DATA[:,1]"ではDATAという21行$\times$2列の変数の中で、2列目のデータを全て$x$へと格納することを意味しています(pythonでは行番号や列番号は0始まりであることに注意してください)。

　最終ブロックは前回のものとほとんど同じです。ただ、今回は**plt.scatter**という散布図を描くための関数を用いています。

#補足　
　上のプログラムではインプットするデータファイル名とアウトプットする画像ファイル名はプログラム内に書いていました。しかし、これではインプットやアウトプットするファイル名を変更するたびにプログラム自体を書き直す必要があり、やや面倒です。ここではプログラム内でファイル名を指定する必要のないより汎用性のあるプログラムを紹介します。以下のプログラムを実行するときは**python plot.py -f sin.dat -o sin.png**という風に実行してください。-fの後にインプットファイル名を入れ、-oの後にアウトプットファイル名を入れます。

```python
#############################################
####### begin import libraries ##############
import numpy as np
import matplotlib.pyplot as plt
import argparse
####### end import libraries ###############
############################################

#############################################
####### begin get argument ##################
parser = argparse.ArgumentParser(description='(ex)program_name.py -f input.dat -o output.png')

parser.add_argument('-f',required=True,type=str,help='Input the data file')
parser.add_argument('-o',required=True,type=str,help='Input the output file')

data_filename = parser.parse_args().f
output_filaname = parser.parse_args().o
####### end get argument ####################
#############################################

#############################################
####### begin read data #####################
DATA = np.loadtxt(data_filename)
x = DATA[:,0]
y = DATA[:,1]
####### end read data #######################
#############################################

#############################################
####### begin plot ##########################
plt.scatter(x,y)
plt.savefig(output_filaname)
plt.show()
####### end plot ############################
#############################################
```
プログラムの説明をします。基本的には先のプログラムと同じですが、importするライブラリに**argparse**が追加され、"get argument"のブロックが追加されています。このブロックが肝です。まず、**argparse.ArgumentParser**という関数を用いて**parse**という変数を生成します。argparse.ArgumentParserの引数の中にある"description=~"の部分はプログラム実行時に"-h"のオプションを付けると表示されるものであり、このプログラムの実行方法を書いておきます(これは無くてもプログラムは回ります。あくまで、使い方を忘れた時のためのものです)。

 次の**parser.add_argument**の部分でそれぞれプログラム実行時に入力した引数をparserに追加します。(上の例では"sin.dat"という引数と"sin.png"という2つの引数を読み込んでいます)。**parser.add_argument**の1つ目の引数に'-f'を入れると、実行コマンドにおいて-fの後ろにある文字列または数字がparserに追加されます。2つ目の引数である"required=True"の部分は、プログラム実行時に1つ目の引数で指定したオプションがない場合にエラーを出すようにしています。この部分は無くてもよいですが、引数を入れるのを忘れた場合に変な場所でエラーが出たりすることを避ける為にもあったほうが無難です。3つ目の引数である"type=~"の部分は該当する引数の型を表しています。この部分も無くてもプログラムは回りますがあった方が無難です。4つ目の変数である"help=~"の部分はプログラム実行時に-hのオプションをつけた場合に表示されるヘルプメッセージを記載しています。この部分が無くてもプログラムは回りますが、変数の意味を忘れた時のためにも書いておくのが無難です。

 読み込んだ引数はこのブロックの下2行のようにして用います。つまり、-fのオプションで入れた引数を用いるときは"parser.parse_args($~$).f"とします。