Python Library/Pandas

[Pandas - Python] Discretization and Binning - cut() (이산화 및 분류)

바보1 2022. 6. 14. 00:31

Discretization and Binning - cut()

 

데이터를 특정 범위에 따라 분류하는 법에 대해 알아보겠습니다.

ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
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, right]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]

cut 함수를 통해 ages를 bins의 범위에 따라 나눴습니다.

 

이때 cats의 데이터가 bin의 어디에 속하는지, 어느 범위에 속하는지 알기 위해서는

codes, 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]], dtype='interval[int64, right]')

또한 value_counts()를 사용하여 범위에 몇 개의 데이터가 들어가는지도 알 수 있습니다.

pd.value_counts(cats)

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

 

 

 

 

 

이때 다른 방식으로도 범위에 따라 나눌 수 있습니다.

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, left]): [[18, 26) < [26, 36) < [36, 61) < [61, 100)]
group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
pd.cut(ages, bins, labels=group_names)

['Youth', 'Youth', 'Youth', 'YoungAdult', 'Youth', ..., 'YoungAdult', 'Senior', 'MiddleAged', 'MiddleAged', 'YoungAdult']
Length: 12
Categories (4, object): ['Youth' < 'YoungAdult' < 'MiddleAged' < 'Senior']

이렇게 범위에 따라 이름(라벨)을 넣을 수도 있습니다.

 

일일이 범위를 지정하기 어렵다면, 몇 개의 범위로 나눌지만 파라미터로 넣어 간단하게 나눌 수 있습니다.

이때 precision은 최대 몇 개의 숫자를 이용하여 나눌 것인지 결정합니다.

data = np.random.rand(20)
pd.cut(data, 4, precision=2)

[(0.32, 0.53], (0.74, 0.95], (0.74, 0.95], (0.53, 0.74], (0.11, 0.32], ..., (0.74, 0.95], (0.11, 0.32], (0.74, 0.95], (0.32, 0.53], (0.74, 0.95]]
Length: 20
Categories (4, interval[float64, right]): [(0.11, 0.32] < (0.32, 0.53] < (0.53, 0.74] < (0.74, 0.95]]

 

data = np.random.randn(1000)  # Normally distributed
cats = pd.qcut(data, 4)  # Cut into quartiles
cats

[(-0.686, -0.0321], (-2.9499999999999997, -0.686], (-2.9499999999999997, -0.686], (-0.0321, 0.613], (-0.0321, 0.613], ..., (0.613, 3.928], (-2.9499999999999997, -0.686], (-0.686, -0.0321], (0.613, 3.928], (-0.686, -0.0321]]
Length: 1000
Categories (4, interval[float64, right]): [(-2.9499999999999997, -0.686] < (-0.686, -0.0321] < (-0.0321, 0.613] < (0.613, 3.928]]
pd.value_counts(cats)

(-2.9499999999999997, -0.686]    250
(-0.686, -0.0321]                250
(-0.0321, 0.613]                 250
(0.613, 3.928]                   250
dtype: int64

정규 분포를 이용하여 데이터를 1000개 뽑았고, 이를 4개의 범위로 분류한 결과입니다.

 

이때 qcut은 확률과 통계의 quantiles을 이용하여 분류합니다.

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

[(-1.187, -0.0321], (-1.187, -0.0321], (-1.187, -0.0321], (-0.0321, 1.287], (-0.0321, 1.287], ..., (1.287, 3.928], (-2.9499999999999997, -1.187], (-1.187, -0.0321], (-0.0321, 1.287], (-1.187, -0.0321]]
Length: 1000
Categories (4, interval[float64, right]): [(-2.9499999999999997, -1.187] < (-1.187, -0.0321] < (-0.0321, 1.287] < (1.287, 3.928]]