Loading [MathJax]/extensions/tex2jax.js

[matplotlib] 74. ColorPickerで色を選択し、クリックしたマーカーを着色する。さらに、色ごとに集計した結果を棒グラフで表示する

ipywidgets

はじめに

ipywidgetsのColorPickerで色を選択し、整列した無着色のマーカーをクリックして着色する方法について説明する。また、色の集計を行い棒グラフで表示する。

コード

%matplotlib
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from ipywidgets import ColorPicker
plt.rcParams['font.size']=12
plt.rcParams['font.family'] = 'sans-serif'
#Using matplotlib backend: Qt5Agg
fig,ax = plt.subplots(figsize=(4,5))
ax.set_title('click on points')
x,y = np.meshgrid(np.linspace(0,25,26),np.linspace(0,25,26))
ax.plot(x,y,'o',c='k', ms=8)
plt.savefig('aquabeads1.png',dpi=100)
plt.show()
with np.errstate(invalid='ignore'):
x[x<2]=np.nan
x[x>23]=np.nan
for i in range(13):
x[2*i,2] = np.nan
x[2*i,:] -= 0.5
fig,ax = plt.subplots(figsize=(5,6))
ax.set_title('click on points')
ax.plot(x,y,'o',mfc="None",mew=1,mec='gray',picker=5,ms=12)
ax.axis('off')
colp = ColorPicker(concise=False,description='marker color:',value='green')
display(colp)
mfcs=[]
def onpick(event):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
plot, = ax.plot(xdata[ind], ydata[ind],'o',mfc=''+colp.value+'',mew=1,mec='gray',ms=12)
mfc = plot.get_markerfacecolor()
mfcs.append(mfc)
fig.canvas.draw()
fig.canvas.mpl_connect('pick_event', onpick)
plt.show()
ser=pd.Series(mfcs)
ser.head()
'''
0 green
1 green
2 green
3 green
4 green
dtype: object
'''
counts = ser.value_counts()
counts
'''
green 83
black 42
red 13
pink 3
dtype: int64
'''
#show bar chart
fig,ax=plt.subplots()
plt.bar(np.arange(len(counts)),counts.values,color=counts.index)
ax.set_xticks(np.arange(len(counts)))
ax.set_xticklabels(counts.index)
for x, y in zip(np.arange(len(counts)),counts.values):
plt.text(x, y, y, ha='center', va='bottom',fontsize='xx-large')
ax.set_ylim(0,counts.values.max()+10)
plt.tight_layout()
view raw aquabeads.py hosted with ❤ by GitHub

解説

モジュールのインポートなど

%matplotlib
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from ipywidgets import ColorPicker
plt.rcParams['font.size']=12
plt.rcParams['font.family'] = 'sans-serif'
#Using matplotlib backend: Qt5Agg
view raw aquabeads.py hosted with ❤ by GitHub

%matplotlibでjupyter lab, notebook内ではなく、別ウインドウでQt5Aggのbackendにより表示する。

バージョン

#version
import ipywidgets
print(ipywidgets.__version__)
7.5.1
import matplotlib
print(matplotlib.__version__)
3.2.0
print(np.__version__)
1.18.1
print(pd.__version__)
1.0.1
view raw aquabeads.py hosted with ❤ by GitHub

データの生成

fig,ax = plt.subplots(figsize=(4,5))
ax.set_title('click on points')
x,y = np.meshgrid(np.linspace(0,25,26),np.linspace(0,25,26))
ax.plot(x,y,'o',c='k', ms=8)
plt.savefig('aquabeads1.png',dpi=100)
plt.show()
view raw aquabeads.py hosted with ❤ by GitHub

np.meshgridでgrid状のデータを作成する。図示すると以下のようになる。

データの加工

with np.errstate(invalid='ignore'):
x[x<2]=np.nan
x[x>23]=np.nan
for i in range(13):
x[2*i,2] = np.nan
x[2*i,:] -= 0.5
view raw aquabeads.py hosted with ❤ by GitHub

xの1以下、24以上をnp.nanとする。さらにxの偶数行のインデックスが2の位置をnp.nanとし、-0.5することでマーカーをずらす。

図の表示

fig,ax = plt.subplots(figsize=(5,6))
ax.set_title('click on points')
ax.plot(x,y,'o',mfc="None",mew=1,mec='gray',picker=5,ms=12)
ax.axis('off')
view raw aquabeads.py hosted with ❤ by GitHub

ColorPickerの表示

colp = ColorPicker(concise=False,description='marker color:',value='green')
display(colp)
view raw aquabeads.py hosted with ❤ by GitHub

ColorPickerでは色のついた四角をクリックすることで出てくるカラーピッカーウインドウから色を選択できる。また、pinkなどの色の名前を直接入力することでも色を選択できる。

onpickイベントの設定

mfcs=[]
def onpick(event):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
plot, = ax.plot(xdata[ind], ydata[ind],'o',mfc=''+colp.value+'',mew=1,mec='gray',ms=12)
mfc = plot.get_markerfacecolor()
mfcs.append(mfc)
fig.canvas.draw()
fig.canvas.mpl_connect('pick_event', onpick)
view raw aquabeads.py hosted with ❤ by GitHub

最初にマーカーの色を入れるための空のリスト(mfcs)を作成しておく。
event.artistをthislineとして、get_xdata()、get_ydata()でクリックした点のdataの配列を取得し、event.indでインデックスを取得することで、クリックした点の座標を取得する。

ax.plot()でmfc=”+colp.value+”とすることでカラーピッカーで選択した色の点がクリックしたマーカーに表示される。

plot.get_markerfacecolor()でマーカーの色を取得し、リストにいれる。このリストは後で集計するために用いる。

fig.canvas.draw()で図を更新する。

fig.canvas.mpl_connect(‘pick_event’, onpick)でイベントを実行可能とする。

色の集計

ser=pd.Series(mfcs)
ser.head()
'''
0 green
1 green
2 green
3 green
4 green
dtype: object
'''
counts = ser.value_counts()
counts
'''
green 83
black 42
red 13
pink 3
dtype: int64
'''
view raw aquabeads.py hosted with ❤ by GitHub

pd.Series()でlistをpandasのシリーズとし、シリーズに対して.value_counts()を行うことで要素のカウントを行った。

集計結果の表示

fig,ax=plt.subplots()
plt.bar(np.arange(len(counts)),counts.values,color=counts.index)
ax.set_xticks(np.arange(len(counts)))
ax.set_xticklabels(counts.index)
for x, y in zip(np.arange(len(counts)),counts.values):
plt.text(x, y, y, ha='center', va='bottom',fontsize='xx-large')
ax.set_ylim(0,counts.values.max()+10)
plt.tight_layout()
plt.savefig('count_aquabeads.png',dpi=120)
plt.show()
view raw aquabeads.py hosted with ❤ by GitHub

plt.bar()で棒グラフを表示する。color=counts.indexとすることでインデックスの色を棒グラフの色とした。
plt.text()で値をそれぞれの棒の上に表示した。

コードをダウンロード(.pyファイル)

コードをダウンロード(.ipynbファイル)

参考

https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20List.html
Event handling and picking — Matplotlib 3.1.2 documentation

コメント