物理の駅 by onsanai

Physics Station → PhSt 質問・疑問・間違いの指摘は、コメントに書くか、直接伝えるときっと良いことがあります。主にWindows or Ubuntu用の記事です

Pythonのmatplotlibの2次元ヒストグラムで値が0のbinの背景を白にする方法

matplotlib.pyplothist2d では、ビンの値が0のとき、背景を無色(白)にできない。

np.ma.masked_where を使い指定する値(以下の例では0)のbinの内容 typenumpy.ma.core.MaskedConstant にすると、 plt.pcolormesh で描画したときにmask部分が塗りつぶされなくなる。

f:id:onsanai:20200113171950p:plainf:id:onsanai:20200113171946p:plain
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(0)
n = 100000
x = np.random.randn(n)
y = (1.5 * x) + np.random.randn(n)

# ビンの数、範囲を指定
nbin_x = 20
nbin_y = 32
range_x = (-5,5)
range_y = (-8,8)

# histgram2dを使ってヒストグラムを生成する
Z, X, Y = np.histogram2d(x,y,bins=[nbin_x,nbin_y],range=[range_x,range_y])
Z = np.rot90(Z) # np.histogram2dの仕様上必要
Z = np.flipud(Z) # np.histogram2dの仕様上必要

# 値が0をマスクする
Z_masked = np.ma.masked_where(Z==0,Z)

# ヒストグラム生成
plt.pcolormesh(X,Y,Z_masked)
plt.xlabel('x')
plt.ylabel('y')
cbar = plt.colorbar()
cbar.ax.set_ylabel('Entries')
plt.show()

ちなみに、愚直な方法でヒストグラムを作った場合=検証用

import numpy as np
import matplotlib.pyplot as plt
np.random.seed(0)
n = 100000
x = np.random.randn(n)
y = (1.5 * x) + np.random.randn(n)

# ビンの数、範囲を指定
nbin_x = 20
nbin_y = 32
range_x = (-5,5)
range_y = (-8,8)

# 愚直な方法でbinを詰める
X, Y = np.mgrid[0:nbin_x+1:1.0, 0:nbin_y+1:1.0]
Z=X*0

wbin_x = (range_x[1]-range_x[0])/nbin_x
wbin_y = (range_y[1]-range_y[0])/nbin_y

for vx,vy in zip(x,y):
    bin_x = (vx-range_x[0])//wbin_x
    bin_y = (vy-range_y[0])//wbin_y
    if bin_x<0:continue
    if bin_y<0:continue
    if bin_x>=nbin_x:continue
    if bin_y>=nbin_y:continue
    Z[int(bin_x),int(bin_y)]+=1
X*=wbin_x
X+=range_x[0]
Y*=wbin_y
Y+=range_y[0]

# 値が0をマスクする
Z_masked = np.ma.masked_where(Z==0,Z)

# ヒストグラム生成
plt.pcolormesh(X,Y,Z_masked)
plt.xlabel('x')
plt.ylabel('y')
cbar = plt.colorbar()
cbar.ax.set_ylabel('Entries')
plt.show()

参照 oceanpython.org