パーマーペンギン(palmerpenguins)

統計で例として使うデータとしては、昔はあやめ(iris)のデータが有名でしたが、それに代わるものとして、palmerpenguins というデータが提案されています。これは南極のパーマーランドの三つの島に住むペンギンたちのデータです。

パーマーペンギン
Artwork by @allison_horst

データは、ここでは seaborn のものを使います:

import seaborn as sns

penguins = sns.load_dataset("penguins")
penguins
    species     island  bill_length_mm  bill_depth_mm  flipper_length_mm  body_mass_g     sex
0    Adelie  Torgersen            39.1           18.7              181.0       3750.0    Male
1    Adelie  Torgersen            39.5           17.4              186.0       3800.0  Female
2    Adelie  Torgersen            40.3           18.0              195.0       3250.0  Female
3    Adelie  Torgersen             NaN            NaN                NaN          NaN     NaN
4    Adelie  Torgersen            36.7           19.3              193.0       3450.0  Female
..      ...        ...             ...            ...                ...          ...     ...
339  Gentoo     Biscoe             NaN            NaN                NaN          NaN     NaN
340  Gentoo     Biscoe            46.8           14.3              215.0       4850.0  Female
341  Gentoo     Biscoe            50.4           15.7              222.0       5750.0    Male
342  Gentoo     Biscoe            45.2           14.8              212.0       5200.0  Female
343  Gentoo     Biscoe            49.9           16.1              213.0       5400.0    Male

[344 rows x 7 columns]
penguins.value_counts("species")
species
Adelie       152
Gentoo       124
Chinstrap     68
dtype: int64
penguins.value_counts("island")
island
Biscoe       168
Dream        124
Torgersen     52
dtype: int64

パーマーペンギンには Adelie(Adélie、アデリーペンギン)、Gentoo(ジェンツーペンギン)、Chinstrap(ヒゲペンギン)という種類があります。島の名前は Biscoe(ビスコー)、Dream(ドリーム)、Torgersen(トージャーセン)です。

いらすとやさんにアデリーペンギンジェンツーペンギンヒゲペンギンが揃っています。

変数名は、species(種)、island(島)、bill_length_mm(くちばしの長さmm)、bill_depth_mm(くちばしの上下幅mm)、flipper_length_mm(ひれの長さmm)、body_mass_g(体重g)、sex(性別、Male=オス、Female=メス)です。

箱ひげ図を描いてみましょう:

sns.boxplot(x="species", y="body_mass_g", data=penguins)
パーマーペンギン

箱ひげ図は、コンピュータグラフィックスがあまり進んでいない1970年代に、John Tukey によって提案されて普及したものです。今なら、同じスペースを使って、より多くの情報を表示することができます。

例えば、図の幅を少し狭くして、箱ひげ図の色を白にし、外れ値を非表示にして、上からストリッププロット(左右にランダムなジッターを加えたドットプロット)をかぶせてみましょう:

plt.figure(figsize=(4.0, 4.8))
  
sns.boxplot(x="species", y="body_mass_g", data=penguins, color="white", fliersize=0)
sns.stripplot(x="species", y="body_mass_g", data=penguins)
パーマーペンギン

sns.boxplot()sns.stripplot() の代わりに sns.violinplot()sns.swarmplot() とすると、バイオリンプロットやスウォームプロットが得られます。

sns.violinplot(x="species", y="body_mass_g", data=penguins)
パーマーペンギン
sns.swarmplot(x="species", y="body_mass_g", data=penguins)
パーマーペンギン

また、pip install git+https://github.com/mparker2/seaborn_sinaplot.git してインポートすれば、シーナプロット sinaplot.sinaplot() も使えます:

[追記] seabornの新しいバージョンでは使えなくなっているようです。とりあえず作者に issue を送っておきましたが、なかなか対応してもらえないようです。とりあえず独自実装の簡単な関数を作っておきました。

import sinaplot

sinaplot.sinaplot(x="species", y="body_mass_g", data=penguins)
パーマーペンギン

ちなみに、箱ひげ図を Matplotlib だけでするなら、次のようになります:

x1 = penguins.query("species == 'Adelie'")["body_mass_g"].dropna()
x2 = penguins.query("species == 'Chinstrap'")["body_mass_g"].dropna()
x3 = penguins.query("species == 'Gentoo'")["body_mass_g"].dropna()
plt.boxplot([x1, x2, x3], labels=["Adelie", "Chinstrap", "Gentoo"])
plt.ylabel("Body Mass (g)")

この最初の4行は次のように書くこともできます:

s = penguins["species"].unique()   # ["Adelie", "Chinstrap", "Gentoo"]
x = [penguins.query(f"species == '{i}'")["body_mass_g"].dropna() for i in s]
plt.boxplot(x, labels=s)
パーマーペンギン

中央値がオレンジになるのが嫌なら plt.boxplot()medianprops=dict(color="black") というオプションを入れます。