[Python] 텍스트 파일 읽어와서 숫자형 데이터 표준화하기 (reading csv or text file, standardizing or normalizing of numeric data)
Python 분석과 프로그래밍/Python 데이터 전처리 2019. 5. 21. 22:29이번 포스팅에서는 (1) text 또는 csv 포맷으로 저장된 텍스트 파일을 Python의 string methods 를 사용하여 파일을 열어서 파싱하여 matrix 로 저장하고, (2) 숫자형 데이터를 표준화(standardization) 혹은 정규화(normalization) 하는 사용자 정의함수를 만들어보겠습니다.
예제로 사용할 text 파일은 전복의 성별과 length, diameter, height, whole_weight, shucked_weight, viscera_weight, shell_weight, rings 를 측정한 abalone.txt 파일 입니다.
1. text 파일을 읽어서 숫자형 값으로 만든 matrix, 라벨을 저장한 vector를 만들기
물론, Pandas 모듈의 read_csv() 함수를 이용하여 편리하게 text, csv 포맷의 파일을 읽어올 수 있습니다.
# importing modules
import numpy as np
import pandas as pd
import os
# setting directory
base_dir = '/Users/ihongdon/Documents/Python'
work_dir = 'dataset'
path = os.path.join(base_dir, work_dir)
# reading text file using pandas read_csv() function
df = pd.read_csv(os.path.join(path, 'abalone.txt'),
sep=',',
names=['sex', 'length', 'diameter', 'height', 'whole_weight',
'shucked_weight', 'viscera_weight', 'shell_weight', 'rings'],
header=None)
# check first 5 lines
df.head()
sex length diameter height whole_weight shucked_weight viscera_weight shell_weight rings
0 M 0.455 0.365 0.095 0.5140 0.2245 0.1010 0.150 15
1 M 0.350 0.265 0.090 0.2255 0.0995 0.0485 0.070 7
2 F 0.530 0.420 0.135 0.6770 0.2565 0.1415 0.210 9
3 M 0.440 0.365 0.125 0.5160 0.2155 0.1140 0.155 10
4 I 0.330 0.255 0.080 0.2050 0.0895 0.0395 0.055 7
위의 Pandas 의 함수 말고, 아래에는 Python의 string methods 를 사용해서 파일을 열고, 파싱하는 간단한 사용자 정의함수를 직접 만들어보았습니다.
위의 abalone.txt 파일의 데이터 형태를 참고해서 파일 이름, 숫자형 변수의 개수, 숫자형 변수의 시작 위치, 숫자형 변수의 끝나는 위치, 라벨 변수의 우치를 인자로 받는 사용자 정의함수를 정의하였습니다. 분석을 하려는 각 데이터셋에 맞게 인자와 함수 code block 을 수정하면 좀더 유연하고 데이터 특성에 적합하게 파일을 불어올 수 있는 사용자 정의함수를 만들 수 있습니다.
def file2matrix(filename, val_col_num, val_col_st_idx, val_col_end_idx, label_idx):
"""
- filename: directory and file name
- val_col_num: the number of columns which contains numeric values
- val_col_st_idx: the index of starting column which contains numeric values
- val_col_end_idx: the index of ending column which contains numeric values
- label_idx: the index of label column
"""
# open file
file_opened = open(filename)
lines_num = len(file_opened.readlines())
# blank matrix and vector to store
matrix_value = np.zeros((lines_num, val_col_num))
vector_label = []
# splits and appends value and label using for loop statement
file_opened = open(filename)
idx = 0
for line in file_opened.readlines():
# removes all whitespace in string
line = line.strip()
# splits string according to delimiter str
list_from_line = line.split(sep=',')
# appends value to matrix and label to vector
matrix_value[idx, :] = list_from_line[val_col_st_idx : (val_col_end_idx+1)]
vector_label.append(list_from_line[label_idx])
idx += 1
return matrix_value, vector_label
Python의 문자열 메소드 (string methods)는 https://rfriend.tistory.com/327 를 참고하세요.
위의 file2matrix() 사용자 정의 함수를 사용하여 abalone.txt 파일을 읽어와서 (a) matrix_value, (b) vector_label 을 반환하여 보겠습니다.
# run file2matrix() UDF
matrix_value, vector_label = file2matrix(os.path.join(path, 'abalone.txt'), 8, 1, 8, 0)
#--- matrix_value
# type
type(matrix_value)
numpy.ndarray
# shape
matrix_value.shape
(4177, 8)
# samples
matrix_value[:3]
array([[ 0.455 , 0.365 , 0.095 , 0.514 , 0.2245, 0.101 , 0.15 , 15. ],
[ 0.35 , 0.265 , 0.09 , 0.2255, 0.0995, 0.0485, 0.07 , 7. ],
[ 0.53 , 0.42 , 0.135 , 0.677 , 0.2565, 0.1415, 0.21 , 9. ]])
#--- vector_label
# type
type(vector_label)
list
# number of labels
len(vector_label)
4177
# samples
vector_label[:3]
['M', 'M', 'F']
2-1. 숫자형 데이터를 표준화(Standardization) 하기
위의 숫자형 데이터로 이루어진 matrix_value 를 numpy를 이용해서 표준화, 정규화하는 사용자 정의함수를 작성해보겠습니다. (물론 scipy.stats 의 zscore() 나 sklearn.preprocessing 의 StandardScaler() 함수를 사용해도 됩니다.)
아래의 사용자 정의 함수는 숫자형 데이터로 이루어진 데이터셋을 인자로 받으면, 평균(mean)과 표준편차(standard deviation)를 구하고, standardized_value = (x - mean) / standard_deviation 으로 표준화를 합니다. 그리고 표준화한 matrix, 각 칼럼별 평균과 표준편차를 반환합니다.
def standardize(numeric_dataset):
# standardized_value = (x - mean)/ standard_deviation
# calculate mean and standard deviation per numeric columns
mean_val = numeric_dataset.mean(axis=0)
std_dev_val = numeric_dataset.std(axis=0)
# standardization
matrix_standardized = (numeric_dataset - mean_val)/ std_dev_val
return matrix_standardized, mean_val, std_dev_val
위의 standardize() 함수를 사용하여 matrix_value 다차원배열을 표준화해보겠습니다.
# rund standardize() UDF
matrix_standardized, mean_val, std_dev_val = standardize(matrix_value)
# matrix after standardization
matrix_standardized
array([[-0.57455813, -0.43214879, -1.06442415, ..., -0.72621157,
-0.63821689, 1.57154357],
[-1.44898585, -1.439929 , -1.18397831, ..., -1.20522124,
-1.21298732, -0.91001299],
[ 0.05003309, 0.12213032, -0.10799087, ..., -0.35668983,
-0.20713907, -0.28962385],
...,
[ 0.6329849 , 0.67640943, 1.56576738, ..., 0.97541324,
0.49695471, -0.28962385],
[ 0.84118198, 0.77718745, 0.25067161, ..., 0.73362741,
0.41073914, 0.02057072],
[ 1.54905203, 1.48263359, 1.32665906, ..., 1.78744868,
1.84048058, 0.64095986]])
# mean per columns
mean_val
array([0.5239921 , 0.40788125, 0.1395164 , 0.82874216, 0.35936749,
0.18059361, 0.23883086, 9.93368446])
# standard deviation per columns
std_dev_val
array([0.12007854, 0.09922799, 0.04182205, 0.49033031, 0.22193638,
0.10960113, 0.13918601, 3.22378307])
2-2. 숫자형 데이터를 정규화(Normalization) 하기
다음으로 척도, 범위가 다른 숫자형 데이터를 [0, 1] 사이의 값으로 변환하는 정규화(Normalization)를 해보겠습니다. normalized_value = (x - minimum_value) / (maximum_value - minimum_value) 로 계산합니다.
def normalize(numeric_dataset):
# normalized_value = (x - minimum_value) / (maximum_value - minimum_value)
# calculate mean and standard deviation per numeric columns
min_val = numeric_dataset.min(axis=0)
max_val = numeric_dataset.max(axis=0)
ranges = max_val - min_val
# normalization, min_max_scaling
matrix_normalized = (numeric_dataset - min_val)/ ranges
return matrix_normalized, ranges, min_val
위의 normalize() 사용자 정의 함수에 matrix_value 다차원배열을 적용해서 정규화 변환을 해보겠습니다. 정규화된 다차원배열과 범위(range = max_val - min_val), 최소값을 동시에 반환합니다.
# run normalize() UDF
matrix_normalized, ranges, min_val = normalize(matrix_value)
# normalized matrix
matrix_normalized
array([[0.51351351, 0.5210084 , 0.0840708 , ..., 0.1323239 , 0.14798206,
0.5 ],
[0.37162162, 0.35294118, 0.07964602, ..., 0.06319947, 0.06826109,
0.21428571],
[0.61486486, 0.61344538, 0.11946903, ..., 0.18564845, 0.2077728 ,
0.28571429],
...,
[0.70945946, 0.70588235, 0.18141593, ..., 0.37788018, 0.30543099,
0.28571429],
[0.74324324, 0.72268908, 0.13274336, ..., 0.34298881, 0.29347285,
0.32142857],
[0.85810811, 0.84033613, 0.17256637, ..., 0.49506254, 0.49177877,
0.39285714]])
# ranges
ranges
array([ 0.74 , 0.595 , 1.13 , 2.8235, 1.487 , 0.7595, 1.0035, 28. ])
# minimum value
min_val
array([7.5e-02, 5.5e-02, 0.0e+00, 2.0e-03, 1.0e-03, 5.0e-04, 1.5e-03, 1.0e+00])
다음번 포스팅에서는 텍스트 파일을 파싱해서 One-Hot Encoding 하는 방법을 소개하겠습니다.
많은 도움이 되었기를 바랍니다.
'Python 분석과 프로그래밍 > Python 데이터 전처리' 카테고리의 다른 글
[Python pandas] DataFrame, Series의 행, 열 개수 세기 (1) | 2019.07.03 |
---|---|
[Python pandas] DataFrame의 문자열 칼럼을 분할하여 일부분으로 새로운 칼럼 만들기 (2) | 2019.07.01 |
[Python] 경로 및 폴더 생성/제거(directory and path management using os), 파일 복사 (file copy using shutil) (0) | 2019.03.03 |
[Python Numpy] 배열에 차원 추가하기 (Adding Dimensions to a Numpy Array) (2) | 2019.02.24 |
[Python Numpy] 배열에서 0보다 작은 수를 0으로 변환하는 방법 (0) | 2019.02.21 |