tropicbirdのブログ

データサイエンス分野への転身を目論む三十路(専門は環境分野)。2019年9月からイギリスの予定。

【学習記録】Python データサイエンスハンドブック(58)

オライリーの「Pythonデータサイエンスハンドブック」の学習記録

4.8.3 複数の凡例

・Matplotlibでは複数の凡例を表示することは簡単ではない。
・plt.legend()やax.legend()で2つ目の凡例を追加しても元の凡例が上書きされてします。
(注意:カラーバーと凡例の共存は簡単で、4.3.2で実践済み)
・新しい凡例はax.add_artist()メソッドを使用して作成する。
・Matplotlib.artist.Artistクラスは、プロットに描画される要素(Figure, Axis, Axes, Legend)などの基底クラス。

fig, ax=plt.subplots()
lines=[]
styles=['-','--','-.',':']
x=np.linspace(0,10,1000)

for i in range(4):
    lines += ax.plot(x, np.sin(x-i*np.pi/2),
                    styles[i],color='black')
ax.axis=('equal')

#一つ目の凡例を生成
ax.legend(lines[:2],['line A','line B'],
         loc='upper right', frameon=False)

#二つ目の凡例を作成
from matplotlib.legend import Legend
leg=Legend(ax, lines[2:],['line C','line D'],
          loc='lower right', frameon=False)
ax.add_artist(leg)

f:id:tropicbird:20190825193239p:plain

4.9 カラーバーのカスタマイズ
import matplotlib.pyplot as plt
plt.style.use('classic')
%matplotlib inline
import numpy as np

fig=plt.figure()
x=np.linspace(0,10,1000)
I=np.sin(x)*np.cos(x[:,np.newaxis])
plt.imshow(I)
plt.colorbar()
fig.savefig('4.9.a.png')

f:id:tropicbird:20190825193300p:plain

fig=plt.figure()
plt.imshow(I,cmap='gray')
fig.savefig('4.9.b.png')

f:id:tropicbird:20190825193316p:plain

4.9.1 カラーバーのカスタマイズ
4.9.1.1 カラーマップの選択

重要!!:カラーマップはモノクロ印刷や色の判別が難しい人を考慮して、定性的カラーマップではなく、輝度が一定の増加をするカラーマップ(順次的カラーマップ)を選んだ方がよい。発散的カラーマップも便利だけど、輝度の面で順次的カラーマップの方がよい。
順次的カラーマップの例:viridis, cubehelix, binary
定性的カラーマップの例:jet, rainbow
発散的カラーマップの例:RdBu, PuOr

【学習記録】Python データサイエンスハンドブック(57)

オライリーの「Pythonデータサイエンスハンドブック」の学習記録

4.8 凡例カスタマイズ
ax.legend(loc='upper left',frameon=False,ncol=2)
fig.savefig('4.8.c.png')

%matplotlib inline
import numpy as np

x=np.linspace(0,10,1000)
fig, ax=plt.subplots()
ax.plot(x,np.sin(x),'-b',label='Sine')
ax.plot(x,np.cos(x),'--r',label='Cosine')
ax.axis('equal')
leg=ax.legend()
fig.savefig('4.8.a.png')

f:id:tropicbird:20190825184049p:plain

ax.legend(loc='upper left',frameon=False)
fig.savefig('4.8.b.png')

f:id:tropicbird:20190825184118p:plain

#ncolで凡例の列数を指定
ax.legend(loc='upper left',frameon=False,ncol=2)
fig.savefig('4.8.c.png')

f:id:tropicbird:20190825184225p:plain

#図書ではfigだけで正常にイメージが表示されているが、実際にするとJupyter上では枠の外側が切れてます。謎。
ax.legend(loc='upper left',frameon=False,ncol=2)
fig

f:id:tropicbird:20190825184246p:plain

ax.legend(fancybox=True, framealpha=1, shadow=True, borderpad=1)
fig.savefig('4.8.e.png')

f:id:tropicbird:20190825184334p:plain

4.8.1 凡例要素の選択

・凡例にはデフォルトですべてのラベル付き要素を含む。
・plotメソッドが返したオブジェクトを使用して凡例を表示する要素とラベルを調整する。

#linesはplt.Line2Dインスタンスのリスト
y=np.sin(x[:,np.newaxis]+np.pi*np.arange(0,2,0.5))
lines=plt.plot(x,y)
plt.legend(lines[:2],['first','second'])

#以下のやり方でも同じ図になる。こっちのほうが分かりやすい。
plt.plot(x,y[:,0],label='first')
plt.plot(x,y[:,1],label='second')
plt.plot(x,y[:,2:])
plt.legend(framealpha=1,frameon=True)

f:id:tropicbird:20190825184402p:plain

4.8.2 点サイズの凡例

・点の大きさを凡例で表すには、ラベルなしのデータを項目なしてプロットすることでこれを実現することができる。

#使うデータセットをネットからダウンロード
!curl -O https://raw.githubusercontent.com/jakevdp/PythonDataScienceHandbook/master/notebooks/data/california_cities.csv

cities=pd.read_csv('california_cities.csv')

#使うデータを抜き出す。
lat, lon=cities['latd'],cities['longd']
population, area=cities['population_total'], cities['area_total_km2']

#プロットの点の色を人口、大きさを面積とした散布図をプロットする。
#この時は人口のカラーバーの凡例のみプロットする。
plt.scatter(lon, lat, label=None,c=np.log10(population),cmap='viridis',s=area, linewidth=0,alpha=0.5)
plt.axis(aspect='equal')
plt.xlabel('longitude')
plt.ylabel('latitude')
plt.colorbar(label='log$_{10}$(population)')
plt.clim(3,7)#←カラーバーの範囲を指定

#点の大きさとラベルを指定したうえで、空のリストをx軸とy軸に渡す。
for area in [100,300,500]:
    plt.scatter([],[],c='k',alpha=0.3,s=area,label=str(area)+'km$^2$')
#空の散布図の凡例を表示する。
plt.legend(scatterpoints=1,frameon=False,
          labelspacing=1,title='City Area')
plt.title('California Cities: Area and Population')

f:id:tropicbird:20190825184425p:plain

【学習記録】Python データサイエンスハンドブック(56)

オライリーの「Pythonデータサイエンスハンドブック」の学習記録

4.7 ヒストグラム、ビニング、密度
        %matplotlib inline
        import numpy as np
        import matplotlib.pyplot as plt
        plt.style.use('seaborn-white')
        data=np.random.randn(1000)
        plt.hist(data)

f:id:tropicbird:20190825164740p:plain

        x1=np.random.normal(0,0.8,1000)
        x2=np.random.normal(-2,1,1000)
        x3=np.random.normal(3,2,1000)

#histtype='stepfilled'のオプションを使うことで異なる分布のヒストグラムを比較する。
        kwargs=dict(histtype='stepfilled',alpha=0.3, normed=True,bins=40)
        plt.hist(x1, **kwargs)
        plt.hist(x2, **kwargs)
        plt.hist(x3, **kwargs)

f:id:tropicbird:20190825164807p:plain

#ヒストグラムを作成せずにbinで区切った範囲のデータ数を確認する。
        counts, bin_edges=np.histogram(data,bins=5)
        print(counts)
        print(bin_edges)

[ 42 240 444 221  53]
[-2.92197069 -1.753291   -0.58461131  0.58406837  1.75274806  2.92142775]
4.7.1 2次元のヒストグラムとビニング
#多変量ガウス分布から得られたx及びy配列のデータを定義する。
mean=[0,0]
cov=[[1,1],[1,2]]
x,y=np.random.multivariate_normal(mean,cov,10000).T
4.7.1.1 plt.hist2d:2次元のヒストグラム
        plt.hist2d(x,y,bins=30,cmap='Blues')
        cb=plt.colorbar()
        cb.set_label('count in bin')

#np.histogramと同様の機能として、np.histogram2dがある。
counts, xedges, yedges=np.histogram2d(x,y,bins=30)

f:id:tropicbird:20190825164836p:plain

4.7.1.2 plt.hexbin:六角形のビニング
        plt.hexbin(x,y,gridsize=30,cmap='Blues')
        cb=plt.colorbar(label='count in bin')

f:id:tropicbird:20190825164852p:plain

4.7.1.3 カーネル密度推定

カーネル密度推定(KDE:Kernel Density Estimation)は空間上の点を塗りつぶし、平滑な関数を得るための方法。

#scipy.statsのパッケージからKDE実装を入手
        from scipy.stats import gaussian_kde

#配列サイズを[N次元、Nサンプル]に揃える。
        data=np.vstack([x,y])
        kde=gaussian_kde(data)

#均一なグリッド上で評価する。
        xgrid=np.linspace(-3.5,3.5,40)
        ygrid=np.linspace(-6,6,40)
        Xgrid,Ygrid=np.meshgrid(xgrid,ygrid)
        Z=kde.evaluate(np.vstack([Xgrid.ravel(),Ygrid.ravel()]))

#結果をイメージとして表示する。
        plt.imshow(Z.reshape(Xgrid.shape),
                  origin='lower',aspect='auto',
                  extent=[-3.5,3.5,-6,6],
                  cmap='Blues')
        cb=plt.colorbar()
        cb.set_label('density')

f:id:tropicbird:20190825164906p:plain

#グリッドを細かくすれば、図も細かくなる。
#np.linspaceの区切りを100にしてみる。
        data=np.vstack([x,y])
        kde=gaussian_kde(data)

        xgrid=np.linspace(-3.5,3.5,100)
        ygrid=np.linspace(-6,6,100)
        Xgrid,Ygrid=np.meshgrid(xgrid,ygrid)
        Z=kde.evaluate(np.vstack([Xgrid.ravel(),Ygrid.ravel()]))

        plt.imshow(Z.reshape(Xgrid.shape),
                  origin='lower',aspect='auto',
                  extent=[-3.5,3.5,-6,6],
                  cmap='Blues')
        cb=plt.colorbar()
        cb.set_label('density')

f:id:tropicbird:20190825164919p:plain

【学習記録】Python データサイエンスハンドブック(55)

オライリーの「Pythonデータサイエンスハンドブック」の学習記録

4.6 密度と等高線

・plt.contour:等高線図
・plt.contourf:塗りつぶした等高線
・plt.imshow:画像の表示

4.6.1 3次元関数の可視化

・z=f(x,y)の関数の等高線を作成する。

%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')
import numpy as np
def f(x,y):
    return np.sin(x)**10+np.cos(10+y*x)*np.cos(x)
<200b>
#np.meshgrid関数を用いて1次元配列から2次元グリッドを構築する。
x=np.linspace(0,5,50)
y=np.linspace(0,5,40)
X,Y=np.meshgrid(x,y)
Z=f(X,Y)

plt.contour(X,Y,Z,colors='black')

f:id:tropicbird:20190825152427p:plain

#cmapのカラーマップはIPytohnではplt.cmモジュールにTab補完で調べられる
#plt.cmap.<TAB>
plt.contour(X,Y,Z,20,cmap='RdGy')

f:id:tropicbird:20190825152444p:plain

plt.contour(X,Y,Z,20,cmap='winter')
plt.colorbar()

f:id:tropicbird:20190825152501p:plain

#plt.contourfではカラーマップが連続的ではなく離散的になる。
plt.contourf(X,Y,Z,20,cmap='RdGy')
plt.colorbar()

f:id:tropicbird:20190825152517p:plain

#plt.imshow()メソッドではカラーマップが連続的になる。
#xとyのグリッドを受けないため、画像の範囲を[xmin,xmax,ymin,ymin]の形式で指定する必要がある。
#aspect='image'とすることで、
#contourでは5対4だった図がxとyの単位を一致させるため正方形になる。
plt.imshow(Z,extent=[0,5,0,5], origin='lower',cmap='RdGy')
plt.colorbar()
plt.axis(aspect='image')

f:id:tropicbird:20190825152536p:plain

contours=plt.contour(X,Y,Z,3,colors='black')
#plt.clabel(contours,inline=True,fontsize=8)
#plt.imshow(Z,extent=[0,5,0,5],origin='lower',cmap='RdGy',alpha=0.5)
#plt.colorbar()

f:id:tropicbird:20190825152558p:plain

contours=plt.contour(X,Y,Z,3,colors='black')
plt.clabel(contours,inline=True,fontsize=8)
#plt.imshow(Z,extent=[0,5,0,5],origin='lower',cmap='RdGy',alpha=0.5)
#plt.colorbar()

f:id:tropicbird:20190825152614p:plain

contours=plt.contour(X,Y,Z,3,colors='black')
plt.clabel(contours,inline=True,fontsize=8)
plt.imshow(Z,extent=[0,5,0,5],origin='lower',cmap='RdGy',alpha=0.5)
plt.colorbar()

f:id:tropicbird:20190825152630p:plain

【学習記録】Python データサイエンスハンドブック(54)

オライリーの「Pythonデータサイエンスハンドブック」の学習記録

4.5 誤差の可視化
4.5.1 基本的なエラーバー

・エラーバーのオプションはplt.errorbarのdocstringに記載

In [1]: import numpy as np
        %matplotlib inline
        import matplotlib.pyplot as plt
        plt.style.use('seaborn-whitegrid')

#plt.errorbar()のfmtは線と点の外観を制御するコード
#fmtはplt.plotの略語と同じ値を使う。
#.は点、kは黒色で表示するという意味
In [2]: #fig=plt.figure()
        x=np.linspace(0,10,50)
        dy=0.8
        y=np.sin(x)+dy*np.random.randn(50)
        plt.errorbar(x,y,yerr=dy,fmt='.k')
        #fig.savefig('4.5a.png')

f:id:tropicbird:20190825140624p:plain

In [2]: #fig=plt.figure()
        plt.errorbar(x,y,yerr=dy,fmt='o',color='black',
        ecolor='lightgray', elinewidth=3, capsize=0)
        #fig.savefig('4.5b.png')

f:id:tropicbird:20190825140643p:plain

4.5.2 連続誤差(←要復習)

・scikit-learn APIを使用してガウス過程回帰(GPR:Gaussian Process Regression)を行う。
・これは柔軟なノンパラメトリック関数を連続的な不確かさを持つデータに当てはめる手法。
・メモ1:scikit-learnのバージョンが0.20以降では、GaussianProcessのクラスが削除されているので、代わりにGaussianProcessRegressorとする。
・引用元
python - scikit-learn GaussianProcessRegressor vs GaussianProcess? Why was GaussianProcess deprecated in version 0.18? - Stack Overflow

・バージョン0.20以前のGaussianProcessのクラス
sklearn.gaussian_process.GaussianProcess — scikit-learn 0.17.1 documentation

・バージョン0.20以降のガウス過程回帰の方法
Gaussian Processes regression: basic introductory example — scikit-learn 0.21.3 documentation

・メモ2:図書のような図面にならなかったので、要復習。学習過程はローカルに保存省略。

【学習記録】Python データサイエンスハンドブック(53)

オライリーの「Pythonデータサイエンスハンドブック」の学習記録

4.4 単純な散布図
In [1]: import matplotlib.pyplot as plt
        plt.style.use('seaborn-whitegrid')
        import numpy as np
4.4.1 plt.plotを使った散布図
x=np.linspace(0,10,30)
y=np.sin(x)
plt.plot(x,y,'o',color='black')

f:id:tropicbird:20190818193846p:plain

#様々なマーカー
rng=np.random.RandomState(0)
for marker in ['o','.',',','x','+','v','^','<','>','s','d']:
    plt.plot(rng.rand(5),rng.rand(5),marker,
            label='marker="{0}"'.format(marker))
    plt.legend(numpoints=1)
    plt.xlim(0,1.8)

f:id:tropicbird:20190818193906p:plain

#線コードなどを共に使うこともできる。
plt.plot(x,y,'-ok') #-:直線,o:円マーカー,k:黒

f:id:tropicbird:20190818193930p:plain

#-pの-は直線、pは五角形(pentagon)マーカー
plt.plot(x,y,'-p',color='gray', markersize=15,linewidth=4,markerfacecolor='white',
markeredgecolor='gray',markeredgewidth=2)
plt.ylim(-1.2,1.2)

f:id:tropicbird:20190818194004p:plain

4.4.2 plt.scatterを使った散布図

・#lt.scatterとplt.plotの違いは点のプロパティをそれぞれ個別に設定できること。

plt.scatter(x,y,marker='o')

f:id:tropicbird:20190818194038p:plain

rng=np.random.RandomState(0)
x=rng.randn(100)
y=rng.randn(100)
colors=rng.rand(100)
sizes=1000*rng.rand(100)

plt.scatter(x,y,c=colors,s=sizes,alpha=0.3,cmap='viridis')#cmapはカラーマップのこと
plt.colorbar()#カラースケールの表示
#color引数(上式のCのこと)はカラースケール(上式のcolorbar()コマンドで表示されるもの)に、
#自動的にマッピングされる。
#size引数(上式のsのこと)はピクセル数で指定される。

f:id:tropicbird:20190818194054p:plain

・カラーマップについての説明サイト
matplotlib - カラーマップについて - Pynote

#scikit-learnのアイリスデータを表現する。
from sklearn.datasets import load_iris
iris=load_iris()
features=iris.data.T

plt.scatter(features[0],features[1],alpha=0.2,
            s=100*features[3],c=iris.target,cmap='viridis')
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1])

f:id:tropicbird:20190818194111p:plain

4.4.3 plotメソッドとscatterメソッドの効率について

・データ数が多くなると、plt.plotの方がplt.scatterよりも効率的。
・大きなデータセットに対してはplt.plotを優先する方ががよい。

【学習記録】Python データサイエンスハンドブック(52)

オライリーの「Pythonデータサイエンスハンドブック」の学習記録

4.3.1 プロットの制御:線の色とスタイル
#色のスタイルの調整
In [1]: plt.plot(x,np.sin(x-0),color='blue')
        plt.plot(x,np.sin(x-1),color='g') #カラーコード(rgbcmyk)による指定
        plt.plot(x,np.sin(x-2),color='0.75') #0から1の間のグレースケールの指定
        plt.plot(x,np.sin(x-3),color='#FFDD44') #16進コードで指定
        plt.plot(x,np.sin(x-4),color=(1,0.2,0.3)) #0から1のRGB値をタプルで
        plt.plot(x,np.sin(x-5),color='chartreuse') #HTMLカラーネーム
#ヒント:色の指定がなければ、デフォルトの色から自動で選択される。

f:id:tropicbird:20190818173020p:plain

#線のスタイルの調整
In [1]: plt.plot(x,x+0, linestyle='solid')
        plt.plot(x,x+1, linestyle='dashed')
        plt.plot(x,x+2, linestyle='dashdot')
        plt.plot(x,x+3, linestyle='dotted')
        plt.plot(x,x+4, linestyle='-')#直線
        plt.plot(x,x+5, linestyle='--')#破線
        plt.plot(x,x+6, linestyle='-.')#一点鎖線
        plt.plot(x,x+7, linestyle=':')#点線

f:id:tropicbird:20190818173041p:plain

#線スタイルとカラーコードを同時に指定することもできる。
#カラーコードはRGBとCMYK(シアン、マゼンダ、黄、黒)カラーシステムの標準的な略語を使用する。
In [1]: fig=plt.figure()
        plt.plot(x,x+0,'-g')
        plt.plot(x,x+1,'--c')
        plt.plot(x,x+2,'-.k')
        plt.plot(x,x+3,':r')

f:id:tropicbird:20190818173102p:plain

4.3.2 プロットの制御:座標軸の範囲

・plt.xlim()とplt.ylim()メソッドを使用することで軸の範囲を調整することができる。

In [1]: plt.plot(x,np.sin(x))
        plt.xlim(-1,11)
        plt.ylim(-1.5,1.5)

f:id:tropicbird:20190818173144p:plain

#軸の方向を逆にしたいときは、引数の順序を逆にする。
In [1]: plt.plot(x,np.sin(x))
        plt.xlim(11,-1)
        plt.ylim(1.5,-1.5)

f:id:tropicbird:20190818173203p:plain

#plt.axis()にリストを引数で渡して範囲を指定することも可能
In [1]: plt.plot(x,np.sin(x))
         plt.axis([-1,11,-1.5,1.5])

f:id:tropicbird:20190818173144p:plain

#謎:plt.axis('tight')でフィットした画像が出力されない。(未解決)
In [1]: plt.plot(x,np.sin(x))
        plt.axis('tight')

f:id:tropicbird:20190818173518p:plain

4.3.3 プロットへのラベル付け
In [1]: fig=plt.figure()
        plt.plot(x,np.sin(x))
        plt.title('A Sine Curve')
        plt.xlabel('x')
        plt.ylabel('sin(x)')

f:id:tropicbird:20190818173638p:plain

In [1]: fig=plt.figure()
        plt.plot(x,np.sin(x),'-g',label='sin(x)')
        plt.plot(x,np.cos(x),':b',label='cos(x)')
        plt.axis('equal')
        plt.legend()

f:id:tropicbird:20190818173656p:plain

#ほとんどのpltメソッドはaxメソッドに置き換えることが可能であるが、一部は異なる。
#plt.legend()→ax.legend()
#plt.plot()→ax.plot()
#plt.xlabel()→ax.set_xlabel()
#plt.ylabel()→ax.set_ylabel()
#plt.xlim()→ax.set_xlim()
#plt.ylim()→ax.set_ylim()
#plt.title()→ax.set_title()
#プロジェクト指向インターフェースの場合、
#plt.axes()のset()を使えば、一行で設定をすべて記述することができる。
In [1]: fig = plt.figure()
        ax=plt.axes()
        ax.plot(x,np.sin(x))
        ax.set(xlim=(0,10),ylim=(-2,2),xlabel='x',
        ylabel='sin(x)',title='A Simple Plot')

f:id:tropicbird:20190818173715p:plain