[Pandas 기초] 자료형(type) 변형, 범주형(category)데이터 처리

업데이트:

1. 데이터 표준화

1-1. 단위 환산 : round()

여기서는 숫자형의 반올림 함수 round()에 대해 알아보자

예제 데이터를 불러와 컬럼명을 지정해주자

import pandas as pd
df = pd.read_csv("~/source/part5/auto-mpg.csv", header=None)
df.columns = ['mpg', 'cyclinders','displacement','horsepower','weight',
             'accerleration','model year','origin','name']
df.head()
mpg cyclinders displacement horsepower weight accerleration model year origin name
0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu
1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320
2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite
3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst
4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino

그리고 mpg_to_kpl라는 단위를 만들고 mpg열에 곱하여 kpl열을 새로 만든다.

mpg_to_kpl = 1.60934/3.78541
df['kpl'] = df['mpg'] * mpg_to_kpl
df.head()
mpg cyclinders displacement horsepower weight accerleration model year origin name kpl
0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu 7.652571
1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320 6.377143
2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite 7.652571
3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst 6.802286
4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino 7.227428

여기서 소수점이 너무 길어 보기가 힘들기 때문에 반올림함수 round()를 사용해보자 round(2)는 소수 둘째짜리까지(셋째자리에서) 반올림하는 것을 의미한다.

df['kpl'] = df['kpl'].round(2)
df.head()
mpg cyclinders displacement horsepower weight accerleration model year origin name kpl
0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu 7.65
1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320 6.38
2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite 7.65
3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst 6.80
4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino 7.23

round()함수는 데이터프레임.round(소숫점자리) 또는 round(데이터프레임, 소숫점자리) 두가지 방법 모두 동일하다. 입력인자에 아무 숫자도 넣지 않으면 소숫점 첫번째 자리에서 반올림 한다.

간단한 예시다.

print(round(1.667))
print(round(1.667,2))
[Output]
2
1.67

1-2. 자료형 변환 : replace(), astype()

이번에는 문자열 함수와 관련있는 replace()함수에 대해 알아보자.
먼저 아까 불러온 데이터의 자료형과 horsepower열을 확인해보자.

print(df.dtypes)
print('\n')
print(df['horsepower'].head(10))
[Output]
mpg              float64
cyclinders         int64
displacement     float64
horsepower        object
weight           float64
accerleration    float64
model year         int64
origin             int64
name              object
dtype: object

0    130.0
1    165.0
2    150.0
3    150.0
4    140.0
5    198.0
6    220.0
7    215.0
8    225.0
9    190.0
Name: horsepower, dtype: object

horsepower열은 숫자형임에도 문자형(object)로 불러와졌다.

그 원인을 unique()함수를 이용해 고유값을 확인해서 알아보자.

df['horsepower'].unique()
[Output]
array(['130.0', '165.0', '150.0', '140.0', '198.0', '220.0', '215.0',
       '225.0', '190.0', '170.0', '160.0', '95.00', '97.00', '85.00',
       '88.00', '46.00', '87.00', '90.00', '113.0', '200.0', '210.0',
       '193.0', '?', '100.0', '105.0', '175.0', '153.0', '180.0', '110.0',
       '72.00', '86.00', '70.00', '76.00', '65.00', '69.00', '60.00',
       '80.00', '54.00', '208.0', '155.0', '112.0', '92.00', '145.0',
       '137.0', '158.0', '167.0', '94.00', '107.0', '230.0', '49.00',
       '75.00', '91.00', '122.0', '67.00', '83.00', '78.00', '52.00',
       '61.00', '93.00', '148.0', '129.0', '96.00', '71.00', '98.00',
       '115.0', '53.00', '81.00', '79.00', '120.0', '152.0', '102.0',
       '108.0', '68.00', '58.00', '149.0', '89.00', '63.00', '48.00',
       '66.00', '139.0', '103.0', '125.0', '133.0', '138.0', '135.0',
       '142.0', '77.00', '62.00', '132.0', '84.00', '64.00', '74.00',
       '116.0', '82.00'], dtype=object)

중간에 ?라는 값이 있기 때문이었다. 이것은 결측치이므로 nan을 부여하자

replace()함수는 replace(기존 문자, 바꿀문자)로 사용하여 기존문자를 바꿔주는 역할을 한다. 이는 시리즈, 데이터프레임에 모두 적용 가능하다.

import numpy as np
df['horsepower'].replace("?", np.nan, inplace=True)      # ?를 NaN으로 교체
df.dropna(subset=['horsepower'], axis = 0, inplace=True) # subset열의 na를 가진 전체행 삭제
df['horsepower'] = df['horsepower'].astype('float')      # horsepower열 실수형으로 변환

print(df['horsepower'].dtype)
[Output]
float64

horsepower열의 ?를 nan으로 교체,
dropna()함수로 horsepower열에 결측치가 있는 row는 제거,
해당 열을 이제 실수형(float)으로 변경했다.

astype()함수는 데이터의 타입을 변경해주는 함수이다. 입력인자는 아래와 같다.

정수형은 .astype(‘int’)
문자형은 .astype(‘str’)
범주형은 .astype(‘category’)

이번에는 origin 열을 확인해 보자.

print(df['origin'].unique())
print(df['origin'].dtype)
[Output]
[1 3 2]
int64

origin열은 숫자형이지만, 1,2,3값만 있는 범주형 변수가 더 어울리는 열이다.
따라서 각 나라이름을 나타내는 문자열로 바꿔주자

replace({변경전1:변경후1, 변경전2:변경후2, ..})로 여러가지 값을 한번에 바꿀 수 있다.

df['origin'].replace({1:'USA',2:'EU',3:'JPN'}, inplace=True)
print(df['origin'].unique())
print(df['origin'].dtype)
[Output]
['USA' 'JPN' 'EU']
object

이제 범주형으로 바꿔보자

df['origin'] = df['origin'].astype('category')
print(df['origin'].dtype)
[Output]
category

2. 범주형(카테고리) 데이터 처리

2-1. 구간분할 : np.histogram(), pd.cut()

다시 돌아와서 horsepower열을 결측치 처리를 통해 실수형(float)으로 변경한 부분까지 돌아오자.

df['horsepower'].replace('?',np.nan, inplace = True)
df.dropna(subset = ['horsepower'], axis=0, inplace=True)
df['horsepower'] = df['horsepower'].astype('float')
df.dtypes
[Output]
mpg              float64
cyclinders         int64
displacement     float64
horsepower       float64
weight           float64
accerleration    float64
model year         int64
origin             int64
name              object
dtype: object

horsepower을 3개의 구간으로 구분해보자
np.histogram()함수는 np.histogram(나눌 리스트, bins = 나눌 구간)의 형태로 사용하고,
두개의 값, counts : 각 구간에 속하는 값의 개수bins_dividers : 경계값 리스트을 반환한다.

count, bins_divders = np.histogram(df['horsepower'], bins=3)
print(count,'\n',bins_dividers)
[Output]
[257 103  32] 
[ 46.         107.33333333 168.66666667 230.        ]

3구간으로 설정했으므로 각 구간에 속하는 값들의 개수(count)와 4개의 경계값(bins_divders)을 반환했다.
이제 이 구간값들을 이용해서 범주형 변수를 추가해보자

pd.cut()함수를 활용하면 자동으로 범주형변수를 생성해주며 간단하게 가능하다.
여기서 include_lowest=True 옵션은 최소값을 포함 할 것이냐에 대한 옵션이다.
즉, 여기서는 구간이 46부터 시작을 하는데 df[‘horsepower’]열의 값이 46보다 작을 경우에도 그냥 이 범주에 포함되도록 해주는 것이다.

bin_names = ['저출력','보통출력','고출력']
df['hp_bin'] = pd.cut(x = df['horsepower'], #데이터 배열
                     bins = bins_divders,    #경계값 리스트
                     labels = bin_names,     #구간명
                     include_lowest = True)  # 첫 경계값 포함여부(구간의 하위값)
df.head()
mpg cyclinders displacement horsepower weight accerleration model year origin name hp_bin
0 18.0 8 307.0 130.0 3504.0 12.0 70 1 chevrolet chevelle malibu 보통출력
1 15.0 8 350.0 165.0 3693.0 11.5 70 1 buick skylark 320 보통출력
2 18.0 8 318.0 150.0 3436.0 11.0 70 1 plymouth satellite 보통출력
3 16.0 8 304.0 150.0 3433.0 12.0 70 1 amc rebel sst 보통출력
4 17.0 8 302.0 140.0 3449.0 10.5 70 1 ford torino 보통출력

변수타입도 범주형(category)으로 알아서 입력됐다.

print(df['hp_bin'].dtypes)
[Output]
category

3. 더미변수 : get_dummies()

모델링을 위한 변수변환 과정에서 범주형변수를 더미변수(0과1)화 하는 것을 원핫인코딩(one-hot-encoding)이라고 한다.
get_dummies()함수는 범주형 변수의 모든 고유값을 각각 새로운 더미변수로 변환해준다.

카테고리(저출력, 보통출력, 고출력)를 0,1의 값을 갖는 개별변수로 변환한다.

horsepower_dummies = pd.get_dummies(df['hp_bin'])
print(horsepower_dummies.head(10))
[Output]
   저출력  보통출력  고출력
0    0     1    0
1    0     1    0
2    0     1    0
3    0     1    0
4    0     1    0
5    0     0    1
6    0     0    1
7    0     0    1
8    0     0    1
9    0     0    1

row마다 각 열의 합은 1이 되야하는건 당연하다.

이외에도 sklearn 라이브러리나 다른 머신러닝 라이브러리에 편리하게 더미변수를 생성해주는 one-hot인코딩 함수들이 많이 존재한다. 관련 포스팅은 추후에 업로드할 예정이다.


Reference

도서 [파이썬 머신러닝 판다스 데이터 분석]을 공부하며 작성하였습니다.

댓글남기기