【Pythonデータ分析】度数分布表の作成【ビニング】

pythonLOGO

Pythonでデータ分析する時、例えば年齢のデータがずらーっとあって、
『それぞれ何人いるの?』
と、全体の傾向を掴むため、度数分布表を作ってヒストグラムを作る。

今回はPythonでデータを小分けにする方法を書きます。

ラベルのある『ビンに詰める、ビンに分ける』という事で『ビニング』と言うそうです。

もっと深く調べたい方は『Python ビニング』で検索すると良いと思います。



例えばこんなデータ

import numpy as np
import pandas as pd

ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]

Pandasのcutオブジェクトを利用

# 18歳~25歳、26歳~35歳、36歳~60歳、61歳以上の4つの分に分割する
bins = [18, 25, 35, 60, 100]

cats = pd.cut(ages, bins)
cats

# [(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]
# Length: 12
# Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
# Categoriesオブジェクトが生成される
cats.codes
# array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1], dtype=int8)

cats.categories
# IntervalIndex([(18, 25], (25, 35], (35, 60], (60, 100]],
#               closed='right',
#               dtype='interval[int64]')
pd.value_counts(cats)

# (18, 25]     5
# (35, 60]     3
# (25, 35]     3
# (60, 100]    1
# dtype: int64

# (は開区間→境界を含まない
# [は閉区間→境界を含む
# という意味

左側を閉区間にする場合

# right=Falseを引数として渡すと左側を閉区間にすることが可能
pd.cut(ages, [18, 26, 36, 61, 100], right=False)

# [[18, 26), [18, 26), [18, 26), [26, 36), [18, 26), ..., [26, 36), [61, 100), [36, 61), [36, 61), [26, 36)]
# Length: 12
# Categories (4, interval[int64]): [[18, 26) < [26, 36) < [36, 61) < [61, 100)]

labelsオプションを設定するとビンの名前を設定できる

group_names = ['Youth', 'youngAdult', 'Middleagged', 'Senior']
pd.cut(ages, bins, labels=group_names)

# ['Youth', 'Youth', 'Youth', 'youngAdult', 'Youth', ..., 'youngAdult', 'Senior', 'Middleagged', 'Middleagged', 'youngAdult']
# Length: 12
# Categories (4, object): ['Youth' < 'youngAdult' < 'Middleagged' < 'Senior']

データの最小値と最大値を基にして、等間隔で区切る場合

# 例えばこんなデータ
data = np.random.rand(20)
print(data)
# [0.66214426 0.90929141 0.06582663 0.491324   0.36464093 0.13885098
#  0.92869376 0.72465602 0.3951001  0.19924998 0.70869471 0.57450103
#  0.73736431 0.19260634 0.75599347 0.43365036 0.66550748 0.63392544
#  0.12680674 0.25738036]

pd.cut(data, 4, precision=2)
# precisionは境界値を小数点以下2桁の精度に設定するためのもの

# [(0.5, 0.71], (0.71, 0.93], (0.065, 0.28], (0.28, 0.5], (0.28, 0.5], ..., (0.28, 0.5], (0.5, 0.71], (0.5, 0.71], (0.065, 0.28], (0.065, 0.28]]
# Length: 20
# Categories (4, interval[float64]): [(0.065, 0.28] < (0.28, 0.5] < (0.5, 0.71] < (0.71, 0.93]]

qcut サンプルの分位点を基準にビンを設定する

# qcut サンプルの分位点を基準にビンを設定する

data = np.random.randn(1000) # 正規分布のデータ
cats = pd.qcut(data, 4) # 4つの四分位範囲のビンに分割

cats
# [(-0.654, -0.0428], (0.657, 3.281], (-0.654, -0.0428], (-0.654, -0.0428], (-0.654, -0.0428], ..., (-2.715, -0.654], (-0.0428, 0.657], (-2.715, -0.654], (-2.715, -0.654], (-0.0428, 0.657]]
# Length: 1000
# Categories (4, interval[float64]): [(-2.715, -0.654] < (-0.654, -0.0428] < (-0.0428, 0.657] <
                                    (0.657, 3.281]]

pd.value_counts(cats)
# (0.657, 3.281]       250
# (-0.0428, 0.657]     250
# (-0.654, -0.0428]    250
# (-2.715, -0.654]     250
# dtype: int64

任意の分位点をビンの境界とする方法

cats = pd.qcut(data, [0, 0.1, 0.5, 0.9, 1.])
cats

# [(-1.196, -0.0428], (-0.0428, 1.291], (-1.196, -0.0428], (-1.196, -0.0428], (-1.196, -0.0428], ..., (-2.715, -1.196], (-0.0428, 1.291], (-1.196, -0.0428], (-2.715, -1.196], (-0.0428, 1.291]]
# Length: 1000
# Categories (4, interval[float64]): [(-2.715, -1.196] < (-1.196, -0.0428] < (-0.0428, 1.291] <
                                    (1.291, 3.281]]

pd.value_counts(cats)
# (-0.0428, 1.291]     400
# (-1.196, -0.0428]    400
# (1.291, 3.281]       100
# (-2.715, -1.196]     100
# dtype: int64



あ、宜しければ・・・。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です