[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
도서 [파이썬 머신러닝 판다스 데이터 분석]을 공부하며 작성하였습니다.
댓글남기기