Python ヒストグラムの重ね合わせ。色付きエッジで表現する場合

 本記事では、下図のように2つのデータを重ね合わせる雛形コードを載せました。色塗り潰しなしの色付きエッジで表示します。図例では2つの重ね合わせですが、数が多い場合に分布の比較がし易くなります。

さらに、下図のように度数分布表をcsvファイルへ出力する仕様です。

 

■本プログラム

#!/usr/bin/env python
# coding: utf-8

# In[1]:


import os
import pandas as pd
import numpy as np
import math
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import japanize_matplotlib
plt.rcParams['font.size'] = 18 # グラフの基本フォントサイズの設定

# データ1のcsvファイルを読み込む
file_path_1 = 'data_dir/data1.csv'
df_1 = pd.read_csv(file_path_1)
data1_np = df_1['Value'].values

min1 = min(data1_np)
max1 = max(data1_np)
data1_size = len(data1_np)
print(min1, max1, data1_size)


# In[2]:


# データ2のcsvファイルを読み込む
file_path_2 = 'data_dir/data2.csv'
df_2 = pd.read_csv(file_path_2)
data2_np = df_2['Value'].values

min2 = min(data2_np)
max2 = max(data2_np)
data2_size = len(data2_np)
print(min2, max2, data2_size)


# In[3]:


# 全データ区間の最小値と最大値を取得
if min1 <= min2:
    my_min = min1 # データ1の最小値を最小値とする
else:
    my_min = min2 # データ2の最小値を最小値とする
    
if max1 >= max2:
    my_max = max1 # データ1の最大値を最大値とする
else:
    my_max = max2 # データ2の最大値を最大値とする
print(my_min, my_max)


# In[4]:


# データ1と2で、データ数が大きい方をデータ数とする
if data1_size >= data2_size:
    N = data1_size
else:
    N = data2_size
print(N)


# In[5]:


# スタージェスの公式より
# 階級数を決める
my_class_size = int(1 + math.log2(N))
print('my_class_size', my_class_size)

# 階級幅(グラフ化には不要)
my_class_width = (my_max - my_min) / my_class_size
print('my_class_width', my_class_width)


# In[6]:


x_name = '寸法出来栄え'
y_name = '個数'
legend_name = 'データ'

plt.hist(data1_np, bins = my_class_size, range = (my_min, my_max), 
         histtype = 'step', edgecolor = 'r', linewidth = 2, label = os.path.basename(file_path_1))
plt.hist(data2_np, bins = my_class_size, range = (my_min, my_max), 
         histtype = 'step', edgecolor = 'k', linewidth = 2, label = os.path.basename(file_path_2))
plt.xlabel(x_name)
plt.ylabel(y_name)
plt.legend(bbox_to_anchor = (1.00, 1), title = legend_name)
plt.grid()
#plt.xlim(0, 10)
#plt.savefig('histogram.jpg')
plt.show()


# In[7]:


# ヒストグラムの数値データを取得する関数
def extract_hist_data_func(DATA, CLASS_SIZE, MIN, MAX, FILE_NAME):
    # 階級幅
    class_width = (MAX - MIN) / CLASS_SIZE
    
    # 階級
    bins = np.arange(MIN, MAX + class_width, class_width)

    # 階級値
    class_value = (bins[1:] + bins[:-1]) / 2
    
    # 度数
    hist = np.histogram(DATA, bins)[0]
    
    # 階級の範囲
    class_name = [f'{bins[i]}以上{bins[i+1]}未満' for i in range(hist.size)]

    # 累積和
    cumsum = hist.cumsum()

    # 相対度数
    relative_hist = hist / cumsum[-1]

    # 累積相対度数
    cumsum_relative_hist = cumsum / cumsum[-1]

    ###
    # 列データをリストで作成
    column_data_list = list(zip(
    class_name, # 1. 階級の範囲
    class_value, # 2. 階級値
    hist, # 3. 度数
    cumsum, # 4. 累積和
    relative_hist, # 5. 相対度数
    cumsum_relative_hist, # 6. 累積相対度数
    ))

    # pandasデータフレームを作成
    df_buf = pd.DataFrame(column_data_list,
                  columns = ['階級', '階級値', '度数', '累積和', '相対度数', '累積相対度数'])

    # インデックスを1から振り直す
    df_buf.index = np.arange(1, len(df_buf) + 1)

    # csvファイルに出力
    df_buf.to_csv(FILE_NAME + '.csv', encoding = 'utf_8_sig')

    
# 作成したヒストグラムデータを抽出する関数を実行
extract_hist_data_func(data1_np, my_class_size, my_min, my_max, 'データ1')
extract_hist_data_func(data2_np, my_class_size, my_min, my_max, 'データ2')

(参考)ヒストグラムを色線ではなくて、色塗りつぶしで表現したい場合は、下記を参考下さい。

hk29.hatenablog.jp

以上

<広告>