matplotlib과 seaborn의 히스토그램으로 빈 폭을 깔끔하게 깔끔하게 정리하십시오.

소개




Icons8 Team

라벨별로 데이터의 분포를 확인하기 위해 히스토그램을 겹쳐 플롯하는 경우는 많지만, 데이터에 따라서는 빈폭의 차이가 눈에 띄는 경우가 있다.
Tableau를 비롯한 BI 툴을 사용하고 있어도 발생하지 않지만 matplotlib이나 seaborn은 마음대로 조정해주지 않으므로 스스로 대응할 필요가 있다.

방법



인수의 bins 를 이용한다.

bins : int or sequence or str, optional
matplotlib.pyplot.hist
bins 는 정수값 뿐만 아니라 sequence 도 받을 수 있으므로,
range 함수에 최대값 최소값을 지정하여 원하는 분할수를 설정하면 된다.

import numpy as np
import matplotlib.pyplot as plt

# ラベルが2種類でデータの分布が異なるDataFrameを用意
df_1st = pd.DataFrame(np.random.normal(loc=20, scale=10, size=100), columns=["val"])
df_1st["target"] = "class_1"
df_2nd = pd.DataFrame(np.random.normal(loc=15, scale=20, size=100), columns=["val"])
df_2nd["target"] = "class_2"

df = pd.concat([df_1st, df_2nd])

빈 폭 보정 전


import matplotlib as plt
import seaborn as sns

# target毎にプロット
for val in df["target"].unique():
    ax = sns.distplot(df.query('target == @val')["val"], kde=False, label=f"target is {val}")

ax.legend()



빈 폭 보정 후


# 最小値
x_min = int(df["val"].min())

# 最大値
x_max = int(df["val"].max())

# 最小値から最大値の範囲で5間隔
range_bin_width = range(x_min, x_max, 5)

# target毎にプロット
for val in df["target"].unique():
    ax = sns.distplot(df.query('target == @val')["val"], bins=range_bin_width, kde=False, label=f"target is {val}")

ax.legend()



보충


bins를 설정하지 않으면 Freeman-Diaconis rule이라는 기술로 빈 수가 결정됩니다.
이 기술은 일반적으로 우수하고 단일 데이터를 플롯 할 때 일반적으로 문제없이 플롯됩니다.

distributions.py
def _freedman_diaconis_bins(a):
    """Calculate number of hist bins using Freedman-Diaconis rule."""
    # From https://stats.stackexchange.com/questions/798/
    a = np.asarray(a)
    if len(a) < 2:
        return 1
    h = 2 * iqr(a) / (len(a) ** (1 / 3))
    # fall back to sqrt(a) bins if iqr is 0
    if h == 0:
        return int(np.sqrt(a.size))
    else:
        return int(np.ceil((a.max() - a.min()) / h))


결론



플롯은 아름답지 않은 플롯은 보이는 상대에게 무례하므로,
최소한 깨끗하게 정돈하는 것은 예의라고 생각한다.

좋은 웹페이지 즐겨찾기