Pythonでグラフを描く⑤折れ線グラフの作成
今回は、新たなデータセットを作成して力強い折れ線グラフを作成することを目標とする。

↑こんな感じの折れ線グラフを描くことが目標。
まずはライブラリーをインポートするおきまりのコードを書く。
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid')#グラフの背景を白くする
%matplotlib inline
次にデータセットを作成する。data1には平均値30標準偏差20で500行1列の乱数、data2には平均値50標準偏差15で500行1列の乱数、data3には平均値60標準偏差10で500行1列の乱数を発生させる。最後にdata_allとしてdata1、data2、data3を纏めておく。
Col=["pre", "post1", "post2"]
data1=np.random.normal(30, 20, (500,1))#平均値30 標準偏差20 500行1列の乱数
data2=np.random.normal(50, 15, (500,1))#平均値50 標準偏差15 500行1列の乱数
data3=np.random.normal(60, 10, (500,1))#平均値60 標準偏差10 500行1列の乱数
data_all=np.concatenate([data1,data2,data3],axis=1)
data_allをデータフレームとしてまとめる。列のタイトルには、pre、post1、post2としておく。
df=pd.DataFrame(data_all,columns=Col)
df.head()

うん。作成した乱数がデータフレームに収まっていることが確認できた。
なぜ、pre、post1、post2という名前にしているかというと、今回は筋トレ前にテストを行い(pre)、筋トレ後にテストを2回行った(post1、post2)と想定した研究データを折れ線グラフとして表すこととしたため。想定した研究の流れは↓図になる。

作成したデータフレームの記述統計を見てみる。
df.describe()

意図通りにdata1では平均値が約30、data2では平均値が約50、data3では平均値が約60となっている。想定した研究では、筋トレ後にスコアが高まったとする疑似データとした。
早速折れ線グラフを書いてみる。matplotlibの機能のplot()を使って、作成したデータフレームを使用して折れ線グラフを作成してみる。
plt.plot(df)

えっ?????( ゚Д゚)?????
よくわからないグラフがでてきた。これは作成したかったグラフではない。おそらくテスト一回ずつのプロットが出てきてしまった。
描きたい折れ線グラフは、pre、post1、post2というテストごとの平均値をプロットした図。
データフレームを作り直す。data1、data2、data3ごとにデータフレームを作成する。
df1=DataFrame(data1)
df2=DataFrame(data2)
df3=DataFrame(data3)
最初のデータフレームは横に連結したが、今回は縦に連結する。データフレームを縦に連結する場合はconcat()を使用する。
df_row=pd.concat([df1,df2,df3])
作成したデータフレームdf_rowを一度CSVファイルとしてはきだし、EXCELでデータを編集する。
df_row.to_csv("sample2.csv")
CSVファイルを開き、一番左の列にidと名前をつけて、1から番号を振る。2列目にはScoreという名前を付ける。3列目にtimingとい名前の列を作成し、idが1から500にはpre、501から1000にはpost1、1000から1500にはpost2とラベルを張っていく。pythoのコードで分からないところで、EXCELで編集したほうが早いならEXCELを使用する。

作成したファイルを上書き保存しておく。作成したファイルをダウンロードできるようにした。
作成したCSVファイルをインポートする。
df_row2=pd.read_csv('sample2.csv')
df_row2.head()

インポートできたことが確認できた。それでは、折れ線グラフを作成する。seabornの機能であるpointplot()というコードを使用する。x軸のデータにtimingを入れ、y軸のデータにScoreを入れる。dataにはCSVから読み込んだデータセット(df_row2)を使う。
sns.pointplot(x='timing',y='Score', data=df_row2)

こんなグラフが出来上がった。目標としていたグラフに一歩近づいた。これではカッコ悪いので、これからグラフを改善していく。
改善ポイントは
・グラフを大きくする。plt.figure(figsize=(20,10))
・折れ線の色を黒色にする。color="black"
・エラーバーを標準偏差に変える。 ci="sd"
・軸ラベルを大きくする。plt.tick_params(labelsize = 30)
・グラフのタイトルをつける。plt.title("Mean", size=50)
・y軸ラベルの名前をつける。plt.ylabel("score", size=50)
・x軸ラベルの名前(timing)を消去するplt.xlabel("")
plt.figure(figsize=(20,10))#グラフの大きさ設定
sns.pointplot(x='timing',y='Score', data=df_row2,color="black",ci="sd")
plt.tick_params(labelsize = 30)#軸ラベルの大きさ
plt.title("Mean", size=50)#グラフのタイトル
plt.ylabel("score", size=50)#y軸ラベル
plt.xlabel("")#x軸ラベルの消去

だいぶ改善されて、見やすいグラフになった。ただ、なんだかひ弱な折れ線グラフでカッコ悪い。もっと力強い折れ線グラフに変える。
力強いグラフへの変更ポイントは、
・grid線を消す。sns.set_style('ticks')
・折れ線グラフの線を太くする。scale=3.0
・エラーバーの線を太くする。errwidth=5.0
・x軸のポイントを示すマーカーを●から■に変える。markers="s"
・y軸の範囲を決める。plt.ylim(0, 80)
plt.figure(figsize=(20,10))
sns.set_style('ticks')#grid線を消す
sns.pointplot(x='timing',y='Score', data=df_row2,color="black",
ci="sd", scale=3.0, errwidth=5.0,markers="s")
plt.tick_params(labelsize = 30)
plt.title("Mean", size=50)
plt.ylabel("score", size=50)
plt.xlabel("")
plt.ylim(0, 80)#y軸の範囲

目標とした折れ線グラフよりカッコいいグラフが作成できた。一応データを確認しておく。preでは平均値がだいたい30で標準偏差が20、post1では平均値がだいたい50で標準偏差が15、post2では平均値が60で標準偏差が10とグラフから分かる。これは、最初に作成したデータセットと一致する。
今回の折れ線グラフの作成のために参考にしたwebページ。
・matplotlibでよく使われるやつを改めてまとめた
https://qiita.com/kakiuchis/items/798c00f54c9151ab2e8b
・seaborn.pointplot
https://seaborn.pydata.org/generated/seaborn.pointplot.html
・matplotlib で指定可能なマーカーの名前
https://pythondatascience.plavox.info/matplotlib/%E3%83%9E%E3%83%BC%E3%82%AB%E3%83%BC%E3%81%AE%E5%90%8D%E5%89%8D
意気揚々とグラフの作成を説明している自分だが、上記に示したコードを覚えてはいない。どんなコードを使うとどういう機能があるかはだいたい把握しているので、コードを思いだすにはいろんな資料を参考にしつつグラフを作成している。
と今日はこんな感じ。