06.2.11
レインクラウドプロットで分布の全体像を一枚に まとめ レインクラウドプロットは、密度曲線の片側だけを残した「雲(半バイオリン)」、個々のデータ点を少し横に散らした「雨(ストリップ)」、中央値と四分位数を示す「水たまり(箱ひげ)」の 3 層を同じ位置に重ね、分布の形・個別の値・要約統計を 1 枚で見せる図です。追加パッケージは要らず、ax.violinplot の頂点座標を np.clip で半分に切り、ax.scatter にジッターを足し、ax.boxplot を細く重ねる matplotlib だけの手順で描けます。バイオリンだけでは見えない「n はいくつか」「外れ値は何個か」、箱ひげだけでは見えない「山は 1 つか、右に裾を引くか」が、Group A〜C の 3 グループで同時に読めます。読み終えると、各層の alpha・s・widths をデータ量に合わせて調整し、論文やレポートのグループ比較を 1 枚にまとめられるようになります。
直感
# 3 つのグループのスコアを比べるとき、箱ひげ図は中央値と四分位数を見せますが、Group C のように右に長く裾を引く形は箱だけでは分かりません。バイオリンプロットは形を見せますが、100 点なのか 10 点なのか、点がどこに実在するのかは隠れます。レインクラウドプロットは欲張りな図で、密度曲線を半分に切って左に「雲」として置き、その右に 1 点ずつのデータを「雨」として降らせ、雲と雨の間に細い箱ひげを「水たまり」として挟みます。1 グループにつき 3 層が縦 1 列に収まるので、横に 3 グループ並べても形・点・要約の対応が崩れません。
何が起きているか(ステップで見る)
# コードを読む前に、この手法が図の上で何をしているかを追ってみましょう。「再生」を押すか、スライダーを動かすと 1 手順ずつ進みます。
見るポイント :密度曲線は「各点に置いた小さな山の合計」。階級の切れ目に左右されない代わりに、山の幅(バンド幅)が形を決める。
Python で描く
# 次のコードは、形の違う 3 グループ(平均 50 の正規分布、平均 62 でばらつきの大きい正規分布、右に裾を引く指数分布)を人工的に作り、半バイオリン・ストリップ・箱ひげの 3 層を positions=[1, 2, 3] の同じ位置に重ねて描きます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import numpy as np
import matplotlib.pyplot as plt
rng = np . random . default_rng ( 42 )
groups = [ "Group A" , "Group B" , "Group C" ]
data = [
rng . normal ( loc = 50 , scale = 8 , size = 120 ),
rng . normal ( loc = 62 , scale = 12 , size = 100 ),
rng . exponential ( scale = 10 , size = 110 ) + 40 ,
]
fig , ax = plt . subplots ( figsize = ( 8 , 5 ))
positions = [ 1 , 2 , 3 ]
# --- half-violin (cloud) ---
vp = ax . violinplot ( data , positions = positions , showextrema = False , widths = 0.6 )
for body in vp [ "bodies" ]:
m = np . mean ( body . get_paths ()[ 0 ] . vertices [:, 0 ])
body . get_paths ()[ 0 ] . vertices [:, 0 ] = np . clip (
body . get_paths ()[ 0 ] . vertices [:, 0 ], - np . inf , m
)
body . set_facecolor ( "#2563eb" )
body . set_alpha ( 0.35 )
# --- strip (rain) ---
for pos , d in zip ( positions , data ):
jitter = rng . uniform ( - 0.08 , 0.08 , size = len ( d ))
ax . scatter (
pos + 0.15 + jitter , d , s = 8 , alpha = 0.45 , color = "#1e40af" , edgecolors = "none"
)
# --- boxplot (puddle) ---
bp = ax . boxplot (
data ,
positions = positions ,
widths = 0.12 ,
patch_artist = True ,
showfliers = False ,
zorder = 3 ,
)
for box in bp [ "boxes" ]:
box . set ( facecolor = "white" , edgecolor = "#1e40af" , linewidth = 1.2 )
for med in bp [ "medians" ]:
med . set ( color = "#ef4444" , linewidth = 2 )
ax . set_xticks ( positions )
ax . set_xticklabels ( groups )
ax . set_ylabel ( "スコア" )
ax . set_title ( "レインクラウドプロット — グループ別スコア分布" )
ax . grid ( axis = "y" , alpha = 0.2 )
fig . tight_layout ()
plt . show ()
実行結果の読み方
# Group A の雲は 50 を中心に左右対称で、雨の点も 35〜65 に均等に散り、箱の中央線は 50 付近にあります。Group B は中央値が 62 前後と高く、雲も雨も A より縦に広がっているので、ばらつきが大きいと読めます。Group C は雲の山頂が 45 付近の低い位置にあり、上に向かって細く長く伸びる右裾の形です。箱の中央線は 47 付近ですが、雨の点が 80 を超える位置にも数個あり、箱ひげ図だけでは「中央値 47 の普通のグループ」に見える分布が、実は歪んでいることが雲と雨で分かります。
使いどころと落とし穴
# レインクラウドプロットが向くのは、論文やレポートで 2〜6 グループの分布を 1 枚で比較し、形・個別の点・要約の 3 つを同時に示したいときです。グループが 10 以上になると各列の横幅が足りず、雲と雨が隣の列に食い込むので、その場合は バイオリンプロット 単体か、要約だけでよければ 箱ひげ図 に戻します。落とし穴は 2 つあります。第一に、サンプル数が 500 を超えると雨の点が潰れて帯になるので、alpha を 0.2 以下、s を 3 程度に下げるか、sample(200) で間引きます。第二に、半バイオリンの向きを列ごとに揃えないと雲と雨が重なって読めません。雲を左、雨を右(pos + 0.15)に統一するのが標準の配置です。
学習ナビ
PHASE 4 · 応用・展開
読んだページに印をつけると、トップページとセクション一覧に進み具合が表示されます(ブラウザ内にのみ保存)。