Wizard Notes

Python, JavaScript を使った音楽信号分析の技術録、作曲活動に関する雑記

matplotlib の散布図の色・アルファ値(透明度)を滑らかにグラデーションさせる(cmap利用)

f:id:Kurene:20210620201741p:plain

データの分析や可視化で散布図を使う時には,プロットしたデータの座標や,そのデータが示すラベルや値に応じて色を変えることが多々あります.

matplotlibでRGBA値を変える方法は、以下のようになっています。

# 全て同じ色・透明度を設定する場合
plt.scatter(x, y, c="red", alpha=0.3)

# 各要素の色・透明度を個別に設定する場合
c = [(0,0,0,1), (0.5,0.5,0.3,0.5)] # RGBA値のタプルを格納した配列
plt.scatter(x, y, c=c)

ここで,各要素の色・透明度を個別に設定する場合,色・アルファ値(透明度)をデータ値に応じて設定する必要があります。これを手動で設定するのは非常に手間がかかります.

このようにデータ値に応じてRGB値を設定する方法としては,matplotlibのcmapを使うのがお薦めです。

Choosing Colormaps in Matplotlib — Matplotlib 3.4.2 documentation

cmap は指定したカラーマップに沿って入力した1次元の値をRGB値に変換してくれます。

f:id:Kurene:20210620212302p:plain
matplotlib colormapの例

そこで,cmapを使い,データの値に応じて色・アルファ値(透明度)を滑らかにグラデーションさせた散布図をプロットするスクリプトを書いてみました。

このスクリプトでは,alpha値についてもデータの値に応じて滑らかに変化させています.

具体的には,x, y の極座標での絶対値をアルファ値に,偏角をRGB値の算出に利用しています。

プロット用スクリプト

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt


length = 500
std = 0.5
x = np.random.normal(0.0, std, length)
y = np.random.normal(0.0, std, length)

r   = np.sqrt(x**2+y**2)
agl = np.arctan(y/x)

for k in range(length):
    if (x[k] < 0 and y[k] > 0) or (x[k] < 0 and y[k] < 0):
        agl[k] += np.pi
    elif (x[k] > 0 and y[k] < 0):
        agl[k] += 2*np.pi
    if x[k] == 0:
        agl[k] = np.pi/2 if y[k] > 0 else 3*np.pi/2
    elif y[k] == 0:
        agl[k] = 0 if x[k] > 0 else np.pi

# 振幅の値でアルファ値を変更
cv     = np.sqrt((agl-np.min(agl)) / (np.max(agl)-np.min(agl)+1e-12))
alphas = (r-np.min(r)) / (np.max(r)-np.min(r)+1e-12)
alphas **= 1.5
alphas[alphas<0.01] = 0.01
    
cmap = plt.cm.jet  
colors = [None for k in range(length)]
for k in range(length):
    c_r, c_g, c_b, _ = cmap(cv[k])
    colors[k] = (c_r, c_g, c_b, alphas[k])

plt.clf()
plt.scatter(x, y, c=colors, s=50, linewidths=1)
plt.xlim([-1.5, 1.5])
plt.ylim([-1.5, 1.5])
plt.grid()
plt.show()