데이터 표준화
자료마다 서로 다른 단위가 섞여 있거나 같은 대상을 다른 형식으로 표현한 경우가 있다. 이처럼 동일한 대상을
표현하는 방법에 차이가 있다면, 분석의 정확도는 현저히 낮아질 것이다. 따라서 데이터 포멧을 일관성 있게 표준화
하는 작업이 무엇보다도 필요하다.
다음은 자동차 연비 데이터셋에서 mpg 열을 바꾸는 과정이다.
mpg는 마일 퍼 갤런으로 우리에게 익숙한 킬로미터 퍼 리터 로 바꿔보겠다.
1마일은 1.60934km이고 1갤런은 3.78541리터이다.
import pandas as pd
df = pd.read_csv('/content/drive/MyDrive/part5/auto-mpg.csv')
df.columns = ['mpg','cylinders','displacement','horsepower','weight',
'acceleration', 'model_year','origin','name']
print(df.head())
print('\n')
mpg_to_kpl = 1.60934/3.78541
df['kpl'] = df['mpg'] * mpg_to_kpl
print(df.head())
print('\n')
df['kpl'] = df['kpl'].round(2)
print(df.head())
mpg cylinders displacement horsepower weight acceleration model_year \
0 15.0 8 350.0 165.0 3693.0 11.5 70
1 18.0 8 318.0 150.0 3436.0 11.0 70
2 16.0 8 304.0 150.0 3433.0 12.0 70
3 17.0 8 302.0 140.0 3449.0 10.5 70
4 15.0 8 429.0 198.0 4341.0 10.0 70
origin name
0 1 buick skylark 320
1 1 plymouth satellite
2 1 amc rebel sst
3 1 ford torino
4 1 ford galaxie 500
mpg cylinders displacement horsepower weight acceleration model_year \
0 15.0 8 350.0 165.0 3693.0 11.5 70
1 18.0 8 318.0 150.0 3436.0 11.0 70
2 16.0 8 304.0 150.0 3433.0 12.0 70
3 17.0 8 302.0 140.0 3449.0 10.5 70
4 15.0 8 429.0 198.0 4341.0 10.0 70
origin name kpl
0 1 buick skylark 320 6.377143
1 1 plymouth satellite 7.652571
2 1 amc rebel sst 6.802286
3 1 ford torino 7.227428
4 1 ford galaxie 500 6.377143
mpg cylinders displacement horsepower weight acceleration model_year \
0 15.0 8 350.0 165.0 3693.0 11.5 70
1 18.0 8 318.0 150.0 3436.0 11.0 70
2 16.0 8 304.0 150.0 3433.0 12.0 70
3 17.0 8 302.0 140.0 3449.0 10.5 70
4 15.0 8 429.0 198.0 4341.0 10.0 70
origin name kpl
0 1 buick skylark 320 6.38
1 1 plymouth satellite 7.65
2 1 amc rebel sst 6.80
3 1 ford torino 7.23
4 1 ford galaxie 500 6.38
자료형 변환
숫자가 문자열로 저장된 경우에, 숫자형으로 변환해야 한다. 이 같은 경우를 자료형 변환이라고 한다.
자료형을 확인하기 위해서는 dtypes 속성을 활용하여 각 열의 자료형을 확인한다.
df = pd.read_csv('/content/drive/MyDrive/part5/auto-mpg.csv', header=None)
df.columns = ['mpg','cylinders','displacement','horsepower','weight',
'acceleration', 'model_year','origin','name']
print(df.dtypes)
print('\n')
mpg float64
cylinders int64
displacement float64
horsepower object
weight float64
acceleration float64
model_year int64
origin int64
name object
dtype: object
마력인 horsepower은 숫자형이 적절할 것이고,
model_year와 origin은 범주형이 적절할 것이다.
그렇다면 먼저 horsepower에 어떤 값들이 있는지 확인해보자.
print(df['horsepower'].unique())
print('\n')
['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']
중간에 있는 ? 문자열을 NaN 값으로 변환해야한다. 그리고 나서 NaN 값을 삭제해주자.
import numpy as np
df['horsepower'].replace('?', np.nan, inplace=True)
df.dropna(subset=['horsepower'], axis=0, inplace=True)
df['horsepower'] = df['horsepower'].astype('float')
print(df['horsepower'].dtypes)
float64
이번에는 origin 열을 살펴본다. origin 열에는 1, 2, 3 의 정수가 들어있지만 USA, EU, JPN을 나타낸다.
replace를 활용한다.
print(df['origin'].unique())
df['origin'].replace({1:'USA', 2:'EU', 3:'JPN'}, inplace=True)
print(df['origin'].unique())
print(df['origin'].dtypes())
[1 3 2]
['USA' 'JPN' 'EU']
object
object는 문자열을 나타내는 자료형이다. 실제로는 origin은 범주형 데이터 (category)가 맞을 것이다.
이를 변경하기 위해서는 astype('category') 메서드를 이용한다.
df['origin'] = df['origin'].astype('category') #category는 범주형
print(df['origin'].dtypes)
category
다음은 model_year이다. model_year은 정수형 자료인데, 연도는 시간적인 순서가 있으므로 범주형으로 변환하는 것이
적절하다.
print(df['model_year'].sample(3))
df['model_year'] = df['model_year'].astype('category')
print(df['model_year'].sample(3))
129 74
162 75
75 72
Name: model_year, dtype: int64
337 80
25 70
63 72
Name: model_year, dtype: category
Categories (13, int64): [70, 71, 72, 73, ..., 79, 80, 81, 82]
범주형 데이터 처리
데이터 분석 알고리즘에 따라서는 연속 데이터를 그대로 사용하기 보다는 일정한 구간으로 나눠서 분석하는 것이
효율적인 경우가 있다. 이처럼 연속 변수를 일정한 구간으로 나누고, 각 구간을 범주형 이산 변수로 변환하는 과정을 구간 분할이라고 한다.
판다스 cut() 함수를 이용하면 연속 데이터를 여러 구간으로 나누고 범주형 데이터로 변환할 수 있다.
'horsepower'를 '저출력', '중간출력', '고출력' 으로 나눠서 표시해보도록 하겠다.
df = pd.read_csv('/content/drive/MyDrive/part5/auto-mpg.csv', header=None)
df.columns = ['mpg','cylinders','displacement','horsepower','weight',
'acceleration', 'model_year','origin','name']
df['horsepower'].replace('?', np.nan, inplace=True)
df.dropna(subset=['horsepower'], axis=0, inplace=True)
df['horsepower'] = df['horsepower'].astype('float')
count, bin_dividers = np.histogram(df['horsepower'], bins=3)
print(bin_dividers)
[ 46. 107.33333333 168.66666667 230. ]
경계값을 구하는 방법에는 numpy 라이브러리의 histogram() 함수를 활용하는 방법이 있다.
나누려는 구간(bin) 개수를 bins 옵션에 입력하면 각 구간에 속하는 값의 개수(count)와 경계값 리스트(bin_dividers)를
반환한다.
판다스 cut() 함수의 옵션을 설정할 수 있다.
앞에서 구한 경계값의 리스트(bin_dividers)를 bins 옵션에 할당하고 각 구간의 이름(bin_names)을 labels 옵션에 할당한다.
include_lowest=True 옵션을 사용하면 각 구간의 낮은 경계값을 포함한다.
bin_names = ['저출력', '보통출력', '고출력']
df['np_bins'] = pd.cut(x=df['horsepower'],
bins=bin_dividers,
labels=bin_names,
include_lowest=True)
print(df[['horsepower', 'np_bin']].head(15))
horsepower hp_bin
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 고출력
10 170.0 고출력
11 160.0 보통출력
12 150.0 보통출력
13 225.0 고출력
14 95.0 저출력
다시 정리하면
x에는 나누고자하는 변수
bins에는 경계값의 리스트
labels에는 각 구간의 이름
include_lowest=True 시에 각 구간의 낮은 경계값을 포함한다.
더미 변수
카테고리를 나타내는 범주형 데이터를 회귀분석 등 머신러닝 알고리즘에 바로 사용할 수 없는 경우가 있는데, 컴퓨터가 인식 가능한 입력값으로 변환해주어야 한다.
이럴 때 숫자 0 또는 1로 표현되는 더미 변수를 사용한다. 0과 1은 크고 작음이 아닌 어떤 특성이 있는지 없는지 여부를
표시하는 것이다.
즉, 해당 특성이 존재하면 1, 존재하지 않으면 0으로 구분하는 개념이다.
이처럼 컴퓨터가 인식할 수 있도록 0과 1만으로 구성되도록 변환하는 것을 원핫 인코딩이라고 부른다.
판다스의 get_dummies() 함수를 사용하면 범주형 변수의 모든 고유값을 각각 새로운 더미 변수로 변환한다.
df['hp_bins'] = pd.cut(x=df['horsepower'],
bins=bin_dividers,
labels=bin_names,
include_lowest=True)
horsepower_dummies = pd.get_dummies(df['hp_bin'])
print(horsepower_dummies.head(15))
저출력 보통출력 고출력
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
10 0 0 1
11 0 1 0
12 0 1 0
13 0 0 1
14 1 0 0
사이킷 라이브러리로도 가능한데, 선형대수의 행렬로 표시가 된다.
from sklearn import preprocessing
#전처리를 위한 encoder 객체 만들기
label_encoder = preprocessing.LabelEncoder()
onehot_encoder = preprocessing.OneHotEncoder()
#label_encoder로 문자열 범주를 숫자형 범주로 변환
onehot_labeled = label_encoder.fit_transform(df['hp_bin'].head(15))
print(onehot_labeled)
print(type(onehot_labeled))
#2차원 행렬로 형태를 변경
onehot_reshaped = onehot_labeled.reshape(len(onehot_labeled), 1)
print(onehot_reshaped)
print(type(onehot_reshaped))
#희소행렬로 변환
onehot_fitted = onehot_encoder.fit_transform(onehot_reshaped)
print(onehot_fitted)
print(type(onehot_fitted))'Study > 혼자 공부하는 판다스' 카테고리의 다른 글
| 혼자 공부하는 판다스 - 데이터프레임의 다양한 응용(함수 매핑, 열 재구성) (0) | 2022.04.26 |
|---|---|
| 혼자 공부하는 판다스 - 데이터 사전처리(정규화, 시계열 데이터) (0) | 2022.04.22 |
| 혼자 공부하는 판다스 - 데이터 사전 처리(누락 데이터 처리, 중복 데이터 처리) (0) | 2022.04.22 |
| 혼자 공부하는 판다스 - Folium 라이브러리 (지도 활용) (0) | 2022.04.21 |
| 혼자 공부하는 판다스 - Seaborn 라이브러리 (0) | 2022.04.21 |