Python Jupyter notebookでpandasを使いCSVを読み込みグラフを描画してpdfなどで保存する方法
Pythonでグラフを描画する方法について
Pythonを知らない人やプログラミング初心者の人はこちらの記事をどうぞ
python用の講座についても無料で勉強できます。
jupyter notebook
昔はIPython Notebookと呼ばれていたが、現在はjupyter notebook(ジュパイターノートブック)となっている便利なものがあります。これでグラフを作る方法についてメモ書きしておきます。
エクセルでグラフを作ってもいいのですが、処理がやや面倒かつMacだとエクセルの動作に不安を覚えます。勝手に落ちたり、立ち上がらなかったりと。
jupyter notebookだと割と簡単で綺麗なグラフがかけます。pythonで動くのでpythonがわかる人ならコードを書くだけで加工ができます。
毎回ググっては忘れるを繰り返しているのでそろそろ覚えたい。
jupyter notebookについてはこちらで書きました。
今回やりたかったこと
IMFが公開している各種経済関連のデータを使って色々と調べたいことがあったのでいい機会なので逐一行動をメモることにしました。
Select Country or Country Groups
pythonでpandasとmatplotlibを使いグラフを作成する
簡単に言うとcsv形式のファイルから特定の情報だけをとってきてそれをいい感じにグラフに描画し、pdf・jpg・png形式で保存したい、というだけです。
それ別にエクセルでやれば良くない?となりますが、jupyter notebook上でやればとても早いですし何よりフリーズしません。また結構キレイなグラフになりますし、グラフのデザインとかもそれなりに拘れます。
ちなみにエクセルのファイルがどのようになっているのかも書いておきます。yearとGDP_rate(%)という列があり、そこに対応するデータが入っています。
year | GDP_rate (%) |
---|---|
1980 | 10 |
1981 | 12 |
1982 | 8 |
1983 | 2 |
1984 | 1 |
〜〜〜 | 〜〜〜 |
ここから特定の行(列)だけを抜き出してグラフにします。それで簡単な説明はあとでするとして、忘れないようにコードを書いておくことにします。
%matplotlib inline import numpy as np import matplotlib.pyplot as plt import pandas as pd import os df = pd.read_csv("/Users/yourname/Desktop/book.csv", encoding="UTF-8") plt.figure(figsize=(8, 6.5)) plt.rcParams["font.size"] = 22 plt.rcParams["xtick.labelsize"] = 12 plt.rcParams["ytick.labelsize"] = 15 plt.rcParams["legend.fontsize"] = 12 plt.grid() year = df["year"] gdp = df["GDP_rate(%)"] plt.axhline(y=0) plt.ylim(ymax=8) plt.ylim(ymin=-8) plt.xlabel("年") plt.ylabel("GDP成長率(%)") plt.plot(year,gdp,"r",marker="o",markersize=2) plt.savefig("/Users/yourname/Desktop/gdp.svg", bbox_inches="tight") plt.savefig("/Users/yourname/Desktop/gdp.pdf", bbox_inches="tight") plt.savefig("/Users/yourname/Desktop/gdp.png", bbox_inches="tight") plt.savefig("/Users/yourname/Desktop/gdp.jpg", bbox_inches="tight")
これは.jpg形式で保存した画像をはてなブログにアップロードしたものになります。
なんか全体的に暗くてダメそうな感じになってしまいました。
こちらはpng形式で保存したものです。なかなか悪くない感じになりました。レポートに貼り付ける画像もエクセルだとメンドくさくてスクリーンショットで済ませてしまうことが多かったのですが、最近はちゃんとpythonで書いてます。
データ数が少ないと恩恵が少なく感じますが、数万点のデータを何度も扱う場合は非常に楽になります。
どういう風に楽になるかというと一度グラフを指定して処理の仕方を記述しておけば勝手に計算してくれるからです。たいていちょっと改変するだけで使いまわせます。
エクセルだとちょっと嫌になる処理でもpythonで書いているとなんだか気が楽になる、そういう感じのものです。
具体的な説明について
%matplotlib inlineでは実行したものの結果がすぐにわかるという機能です。
大学とかだとこれでメモとったりしてたら強そう。簡単に情報共有できるし。
これらはグラフのフォントや文字サイズをいい感じに調整するための部分です。ちょっと文字が多すぎたので普段よりも小さめにしています。
plt.figure(figsize=(8, 6.5)) plt.rcParams["font.size"] = 22 plt.rcParams["xtick.labelsize"] = 12 plt.rcParams["ytick.labelsize"] = 15 plt.rcParams["legend.fontsize"] = 12 plt.grid()
これでcsv形式のファイルを読み込みdf(データフレーム)として使用します。
そしてyearにはcsvのyear列を取得したものを、gdpにはGDP_rate(%)列を取得したものを入れておきます。
df = pd.read_csv("/Users/yourname/Desktop/book.csv", encoding="UTF-8") year = df["year"] gdp = df["GDP_rate(%)"]
データフレームはこんな感じになっています。だいたいエクセルっぽいやつという認識です。
これでpythonの描画を実行します。普通の折れ線グラフに実際の点の部分にマーカーをサイズ"2"で埋め込んでいます。色々調べるともっとキレイにできそうですが、これで十分な気がします。
plt.plot(year,gdp,"r",marker="o",markersize=2)
考えられるエラーとその対策
AttributeError: ‘Series’ object has no attribute ‘find’
これはpandasを使っているとよく出るエラーです。
メインの説明はstackoverflowに任せますが、自分が詰まった時のエラーを紹介します。
csvの数値表示はたまに親切で桁表示をしてくれているのですが、それが原因でした。
例:5000と5,000
まさかこれが原因とは知らなかったので時間を無駄にしました。治し方とかは簡単でエクセルでその列または行を指定し、数値表示にさせます。その時に桁表示のオプションをつけなければ治ります。
KeyError: “[‘ ’] not in index”
指定された行または列などが存在していないという意味です。基本的にタイプミスで出てきます。
上の例でいうと、yearがyaerとかになっているとKeyError: “[‘yaer’] not in index"とか表示されます。
TypeError: Can’t convert ‘int’ object to str implicitly
intと文字列で間違って操作をしているというメッセージです。
この場合だとエラーが発生します。
i = 5 print("this is five" + i)
治した場合が下のものです。簡単そうに見えますが、疲れている時にはよく出てくるエラーです。
i = 5 print("this is five" + str(i))
UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0x8c in position 0: invalid start byte
読み込んでいるcsvがUTF-8形式ではなく、SHIFT-JIS形式だった時に発生します。日本語の文字化けですね。
その逆のSHIFT-JISをUTF-8形式で読み込もうとしていた場合でも同様にエラーが発生します。csvの形式に合わせてエンコーディングを指定しましょう。
# UTF-8 df = pd.read_csv("/Users/yourname/Desktop/book.csv", encoding="UTF-8") # SHIFT-JIS df = pd.read_csv("/Users/yourname/Desktop/book.csv", encoding="SHIFT-JIS")
seabornを使った場合
堅苦しくない感じのグラフができます。
seabornを使うとヒートマップ形式のグラフが作成できたりします。理系の研究職では便利になってくる機能で、割と簡単に使えるようになるはずです。
df(データフレーム)にcsvを読み込みます。
seabornの場合では直接、xとyにどこの列かという情報を与えています。これだけで勝手にグラフを作ってくれます。
%matplotlib inline import numpy as np import matplotlib.pyplot as plt import pandas as pd import os import seaborn as sns df = pd.read_csv("/Users/yourname/Desktop/book.csv", encoding="UTF-8") df.plot(x = 'year',y = 'GDP_rate(%)') plt.savefig("/Users/yourname/Desktop/seaborn.png", bbox_inches="tight")
df.plot(x = ‘year’,y = ‘GDP_rate(%)’,marker=‘o’,linestyle=‘’)と少しのオプションを与えるとグラフの形式を変更できます。
そして簡単にヒストグラムだったり分散だったりというのが計算なしで描画可能です。今回のデータにヒストグラムの描画は有効とは思えませんが、例として。
sns.set_style('whitegrid') sns.distplot(df['GDP_rate(%)'],bins=100,color='green') plt.savefig("/Users/yourname/Desktop/seaborn.png", bbox_inches="tight")
複数のグラフを並べたいときに使う方法についてです。TeXやwordでは図を並べる方法が備わっていてそれなりに便利ですが、なぜか思い通りにやってくれない時などがあります。
思ったようなレイアウトにならないような場合は自分で最初から並べておきましょう。
今回はplt.subplot(2, 1, 1)で、(2,1,1)なので2行、1列、一つ目という意味です。並べる配置とかの設定ですね。
plt.figure(figsize=(8, 6.5)) plt.rcParams["font.size"] = 22 plt.rcParams["xtick.labelsize"] = 15 plt.rcParams["ytick.labelsize"] = 20 plt.rcParams["legend.fontsize"] = 18 GDP_list = ['GDP_rate(%)','GDP_US'] plt.subplot(2, 1, 1) plt.plot(df['year'],df['GDP_japan']) plt.legend() plt.subplot(2, 1, 2) plt.plot(df['year'],df['GDP_US']) plt.legend()
グラフを4つに増やした場合とグラフ中にテキストを埋め込んだ場合についてです。
もうちょっとスマートにやる方法もあるはずですが、4つしかないので手打ちしました。地味にすごいと思った機能の一つです。
num_rows = 2 num_cols = 2 title_size = 26 plt.figure(figsize=(8, 6.5)) plt.rcParams["font.size"] = 9 plt.rcParams["xtick.labelsize"] = 9 plt.rcParams["ytick.labelsize"] = 20 plt.rcParams["legend.fontsize"] = 11 plt.subplots_adjust(wspace=0.2, hspace=0.3) # [1] ax = plt.subplot2grid((num_rows, num_cols), (0,0)) ax.text(2010,6,"回復") ax.plot(2010,6,marker="o",markersize=5,color="red") ax.plot(df['year'],df['GDP_japan']) # [2] ax = plt.subplot2grid((num_rows, num_cols), (0,1)) ax.text(1995,6,"1995です") ax.plot(1995,6,marker="o",markersize=5,color="red") ax.plot(df['year'],df['GDP_japan']) # [3] ax = plt.subplot2grid((num_rows, num_cols), (1,0)) ax.plot(df['year'],df['GDP_japan']) ax.plot(2008,6,marker="o",markersize=5,color="red") ax.text(2008,6,"大幅下落") # [4] ax = plt.subplot2grid((num_rows, num_cols), (1,1)) ax.text(2017,6,"予測値です") ax.plot(2017,6,marker="o",markersize=5,color="red") ax.plot(df['year'],df['GDP_japan']) plt.show()
今回はアメリカと日本のGDP成長率を見てみました。2017年以降のデータはIMFによる見積もり値です。二つの線を引くのは簡単でもう一つplotを追加すればいいだけです。
今は2本ですがこれ以上、線の数が増える場合はforループで回した方が効率が良いと思います。
plt.legend()で凡例をつけてわかりやすくしています。
plt.figure(figsize=(8, 6.5)) plt.rcParams["font.size"] = 22 plt.rcParams["xtick.labelsize"] = 15 plt.rcParams["ytick.labelsize"] = 20 plt.rcParams["legend.fontsize"] = 18 GDP_list = ['GDP_rate(%)','GDP_US'] # for gdp in GDP_list: plt.plot(df['year'],df['GDP_japan']) plt.plot(df['year'],df['GDP_US']) plt.legend()
ピアソンの相関関数でアメリカと日本のGDP成長率の相関を見てました。正直なところ、統計関連は完全に苦手なのですが、pythonを使うとなんとなくできるようになります。
ピアソンの相関関数が正の値(0.4)なので日本のGDP成長率とアメリカの成長率は相関していると言えます。直感的にもそれはそうと言った感じです。
横軸とか縦軸とかは今回はいい加減にしています。
sns.jointplot('GDP_japan','GDP_US',df,kind='scatter',color='purple')
ちょっとかっこよくして見ました。
sns.jointplot('GDP_japan','GDP_US',df,kind='kde',color='m')
こういう方法はググりながらでもできますが、最初に体系的に勉強しておくとあとが楽です。
Udemyのデータサイエンスコースではこのようなグラフの描写からデータの分析まで丁寧に勉強できました。Udacityのやつも良かったですけどね。
Jupyter notebookを使ってデータサイエンスの講義をやってくれます。けっこうお気に入りです。
まとめ
- pythonでキレイなグラフの書き方を探した
- jupyter notebookはやっぱり便利
[f:id:what_a_day:20170211001406p:plain]
ちなみにこんな感じのpythonでもっとキレイなグラフや独特なグラフを使いたい場合はこちらの記事を参考にしていただければと思います。
[http://www.what-a-day.net/entry/2016/11/12/100000:embed:cite]