医療職からデータサイエンティストへ

統計学、機械学習に関する記事をまとめています。

pythonで層別、グループ別グラフを作成する

データの可視化をする上で、性別ごとのヒストグラムや、年代ごとの折れ線グラフなど、ある特定の層やグループごとに色分けをしてグラフをかくことがあります。今回は、簡単にグループごとの色分けグラフを書くための、2つの方法をご紹介します。

積み上げ棒グラフを一瞬で作成する方法も、ご紹介しています。

www.medi-08-data-06.work

seabornでかく

1つ目は、seabornを使う方法です。seabornは、リッチなグラフを書けることで有名ですが、グループ別のグラフもhueという引数で簡単にかくことができます。

初めに、可視化用の仮想健康診断データを作っておきます。

import random
import seaborn as sns
import matplotlib.pyplot as plt 
import pandas as pd
import numpy as np

# 仮想の健康診断データ
random.seed(123)
gender =  np.random.choice(["Men", "Women"], size=100, replace=True)
age = np.random.choice(np.arange(20, 60, 10), size=100, replace=True)
height = np.where(gender == "Men", np.random.normal(170, 10, 100), np.random.normal(150, 10, 100))
weight = height - 100 + np.random.normal(0, 10, 100)

medical_data = pd.DataFrame({"gender":gender, "age":age, "height":height, "weight":weight})
gender age height weight
Men 30 169.69 79.1459
Men 40 192.411 80.2841
Men 30 178.483 89.89
Women 50 144.909 48.1535
Women 40 153.979 46.9225
# 性別の身長ヒストグラム
plt.figure(figsize=(4.2, 3))
sns.histplot(x="height", data=medical_data, hue="gender", binwidth=5, palette={"Men":"blue", "Women":"Orange"})
plt.show()

seaborn

簡単ですね!

matplotlibでかく

2つめは、集計用の関数であるgroupbymatplotlibを組み合わせる方法です。 groupbyを適応したデータフレームをfor文に入れてかきます。

plt.figure(figsize=(4.2, 3))
for key, df in medical_data.groupby("gender"):
    # ここで色を指定する。
    color = "blue" if key == "Men" else "Orange"
    plt.hist(df["height"], label=key, alpha=0.5, edgecolor="black")
    plt.legend(title="gender")
    plt.xlabel("height")
    plt.ylabel("Count")

matplotlib

少しトリッキーに見えますが、中身は単純です。groupbyを適応したデータフレームをfor文に入れると、groupingに用いたkeyとデータフレームがタプルになって返ってきます。それをmatplotlibにわたせば、グルーブ別のグラフを書くことができます。 matplotlibを使って細かく調整したい方はこちらですね!

ちなみにグループごとでグラフを分けたい場合、subplotを使えば実現できます。

plt.figure(figsize=(4.2, 3))
for i, key_df in enumerate(medical_data.groupby(["gender"]), 1):
    plt.subplot(1, 2, i)
    key = key_df[0]
    df = key_df[1]
    plt.title(key)
    color = "blue" if key == "Men" else "Orange"
    plt.hist(df["height"], alpha=0.5, edgecolor="black", color=color)
    plt.xlabel("height")
    plt.ylabel("Count")
    plt.tight_layout()
    

層別ヒストグラム

2要因のグラフ

ついでに2つの要因でのグラフも書いてみましょう。ここでは、性別、年代別の身長体重の散布図を書いてみます。

seabornhueは、1つの要因でしか層別化できないため、先にデータを加工する必要があります。

# 性別、年代別の身長と体重散布図
# 性別に年代を結合して、新たなグループを作成する。
medical_data["gender_age"] = medical_data["gender"].str.cat(medical_data["age"].astype(str), sep="_")
# カテゴリーの並び順を設定
group_order = sorted(medical_data["gender_age"].unique())

plt.figure(figsize=(8.4, 6))
sns.scatterplot(x="height", y="weight", data=medical_data, hue="gender_age", hue_order=group_order)
plt.show()

層別散布図

matplotlibでは、labelを加工する必要がありますが、groupbyに変数を入れるだけでOKです。

plt.figure(figsize=(8.4, 6))
for key, df in medical_data.groupby(["gender", "age"]):
    # ここで色を指定する。
    plt.scatter(df["height"], df["weight"], label="_" .join([key[0], str(key[1])]))
    plt.legend(title="gender_age")
    plt.xlabel("height")
    plt.ylabel("weight")

層別散布図

まとめ

seabornmatplotlibの使い分けとしては、

  • 簡単にリッチなグラフを書きたい→seaborn
  • グラフの細かいところまで調整したい→matplotlib

かなと思います。個人的には、いちいちseabornをimportするのが面倒なため、matplotlibをよく使ってます。 こればかりは好みの問題ですね、、

※本記事は筆者が個人的に学んだこと感じたことをまとめた記事になります。所属する組織の意見・見解とは無関係です。