본문 바로가기
Tech/Python

Data Handling - Numerical Data

by Jyubaeng2 2023. 8. 18.

Handling Numeric Data (숫자형 데이터 처리)란?

숫자형 데이터를 처리하는 방법은 데이터 전처리 과정 중에서도 중요한 부분입니다. 본문에서는 숫자형 데이터를 다루는 주요 기술과 개념을 설명하겠습니다.

 

1. 결측값 처리: 결측값은 데이터셋에서 값이 비어 있는 경우를 의미합니다. 이러한 결측값은 분석 및 모델링 작업에서 문제를 일으킬 수 있으므로 적절한 처리가 필요합니다. 주요 결측값 처리 방법에는 평균값, 중앙값, 최빈값으로 채우기, KNN을 이용한 예측 값 채우기, 결측값을 가지고 있는 행 제거 등이 있습니다.

 

2. 특성 스케일링: 다양한 특성들의 범위 및 단위가 다를 경우, 일부 특성이 모델링에 불리한 영향을 줄 수 있습니다. 따라서 특성을 스케일링하여 같은 범위로 조정하거나 표준화/정규화를 통해 평균이 0이 되고 표준편차가 1이 되도록 만들어 줍니다. 이로써 모델이 특성들을 더 공정하게 다룰 수 있게 됩니다.

 

3. 이상치 처리: 이상치는 데이터 내에서 다른 값들과 극단적으로 다른 값입니다. 이상치는 모델 성능을 해치거나 분석 결과를 왜곡시킬 수 있습니다. 따라서 이상치를 탐지하고 처리하는 방법이 필요합니다. 주로 z-score, IQR(Interquartile Range) 등을 이용하여 이상치를 탐지하고 대체하거나 제거하는 등의 처리를 수행합니다.

 

4. 특성 변환: 특성 변환은 기존 특성들을 조합하여 새로운 특성을 생성하는 과정을 말합니다. 다항 특성 생성, 로그 변환, 지수 변환 등의 방법을 사용하여 데이터 분포를 조정하거나 비선형성을 추가할 수 있습니다.

 

5. 클러스터링: 비슷한 특성을 가진 데이터를 클러스터로 그룹화하거나 군집화하는 작업을 의미합니다. 클러스터링은 데이터 유형을 이해하고 유사한 그룹을 발견하는 데 유용합니다.

 

숫자형 데이터를 처리할 때 이러한 접근 방법과 기술들을 조합하여 데이터의 품질을 향상시키고 모델의 성능을 개선할 수 있습니다. 하나하나 알아보도록 하겠습니다.

Rescaling a feature (특성 재조정)

특성 재조정은 특성의 값을 다른 범위로 변환하여 모델의 성능을 향상시키는 데 도움을 주는 프로세스입니다. 주로 특성들이 다른 범위에 분포되어 있는 경우에 사용됩니다.

 

이를 통해 모델이 특정 특성의 값에 민감하게 반응하지 않고, 특성 간에 공정한 영향을 미치도록 할 수 있습니다.

 

특성 재조정에는 여러 가지 방법이 있습니다. 가장 일반적인 두 가지 방법은 Min-Max ScalingStandardization입니다.

  1. Min-Max Scaling (최소-최대 스케일링):
    이 방법은 특성의 값을 새로운 범위로 변환하는 기법입니다. 주로 0과 1 사이의 범위로 변환됩니다. 모든 값들은 원래 값에서 최소값을 뺀 후, 그 차이를 최대값과 최소값의 차이로 나누어 계산됩니다.
  2. Standardization (표준화):
    이 방법은 평균을 빼고 표준 편차로 나누어 값을 변환합니다. 결과적으로, 변환된 값들은 평균을 중심으로 분포하며, 표준 편차 단위로 스케일링되어 특성들의 분포를 조정합니다.

아래에는 두 방법을 사용하여 특성을 재조정하는 일반적인 예제 코드를 보여드리겠습니다.

from sklearn.datasets import load_boston
from sklearn.preprocessing import MinMaxScaler, StandardScaler
import pandas as pd

# 보스턴 주택 가격 데이터셋 불러오기
boston = load_boston()
data = boston.data
feature_names = boston.feature_names

# Create a DataFrame from the dataset
df = pd.DataFrame(data, columns=feature_names)

# Min-Max Scaling
minmax_scaler = MinMaxScaler()
df_minmax = pd.DataFrame(minmax_scaler.fit_transform(df), columns=feature_names)

# Standardization
standard_scaler = StandardScaler()
df_standard = pd.DataFrame(standard_scaler.fit_transform(df), columns=feature_names)

# Display the first few rows of scaled dataframes
print("Min-Max Scaled:")
print(df_minmax.head())

print("\nStandardized:")
print(df_standard.head())

이 코드에서는 보스턴 주택 가격 데이터셋을 불러온 다음, MinMaxScalerStandardScaler를 사용하여 특성을 재조정합니다. 결과적으로 두 가지 방법으로 재조정된 데이터프레임을 출력합니다.

 

sklearn.preprocessing 모듈의 MinMaxScaler를 사용하여 보스턴 주택 가격 데이터셋의 숫자형 특성 값을 두 지정된 값 사이로 재조정하는 방법을 코드로 보여드리겠습니다.

from sklearn.datasets import load_boston
from sklearn.preprocessing import MinMaxScaler
import pandas as pd

# 보스턴 주택 가격 데이터셋 불러오기
boston = load_boston()
data = boston.data
feature_names = boston.feature_names

# 데이터셋을 데이터프레임으로 생성
df = pd.DataFrame(data, columns=feature_names)

# 재조정할 범위 정의 (0부터 1까지)
min_value = 0
max_value = 1

# MinMaxScaler 초기화
scaler = MinMaxScaler(feature_range=(min_value, max_value))

# 숫자형 특성을 학습 및 변환
numerical_features = df.columns
df_scaled = pd.DataFrame(scaler.fit_transform(df[numerical_features]), columns=numerical_features)

# 재조정된 데이터셋의 처음 몇 행 출력
print(df_scaled.head())

출력 결과 (재조정된 데이터셋):

       CRIM    ZN     INDUS  CHAS    NOX  ...     RAD       TAX   PTRATIO       B   LSTAT
0  0.000000  0.18  0.067815   0.0  0.314 ...  0.0000  0.208015  0.287234  1.0000  0.0897
1  0.000236  0.00  0.242302   0.0  0.172 ...  0.0435  0.104962  0.553191  1.0000  0.2046
2  0.000236  0.00  0.242302   0.0  0.172 ...  0.0435  0.104962  0.553191  0.9897  0.0633
3  0.000293  0.00  0.063050   0.0  0.131 ...  0.0869  0.066794  0.648936  0.9949  0.0335
4  0.000705  0.00  0.063050   0.0  0.131 ...  0.0869  0.066794  0.648936  1.0000  0.0993

[5 rows x 13 columns]

위 코드에서는 먼저 sklearn.datasetsload_boston()을 사용하여 보스턴 주택 가격 데이터셋을 불러옵니다. 그런 다음 데이터셋을 데이터프레임으로 생성하고, 재조정할 숫자형 특성 값의 범위를 min_valuemax_value로 정의합니다.

 

MinMaxScaler를 지정된 특성 범위로 초기화한 후, 데이터셋의 숫자형 특성을 스케일링하는 과정을 보여드렸습니다. 스케일링된 값은 df_scaled 데이터프레임에 저장됩니다.

 

출력 결과는 재조정된 숫자형 특성을 0에서 1 사이로 재조정한 데이터셋의 처음 몇 행을 보여줍니다. 이렇게 하면 모든 특성이 동일한 범위로 스케일링되며, 큰 값이 분석을 지배하지 않도록 합니다.

 

StandardScaler를 사용하여 특성을 평균이 0이고 표준편차가 1이 되도록 변환할 수 있습니다. 아래는 StandardScaler를 사용하여 보스턴 주택 가격 데이터셋을 변환하는 코드 예제와 결과입니다.

from sklearn.datasets import load_boston
from sklearn.preprocessing import StandardScaler
import pandas as pd

# 보스턴 주택 가격 데이터셋 불러오기
boston = load_boston()
data = boston.data
feature_names = boston.feature_names

# 데이터프레임 생성
df = pd.DataFrame(data, columns=feature_names)

# StandardScaler 초기화
scaler = StandardScaler()

# 특성을 평균이 0이고 표준편차가 1이 되도록 변환
scaled_data = scaler.fit_transform(df)

# 결과 출력
print("Original Data:")
print(df.head())
print("\nScaled Data (mean=0, std=1):")
print(scaled_data)

위 코드에서 StandardScaler 클래스를 사용하여 보스턴 주택 가격 데이터셋을 변환합니다. 변환된 데이터는 평균이 0이고 표준편차가 1이 되도록 스케일링됩니다.

 

위 코드를 실행한 결과는 다음과 같습니다:

Original Data:
      CRIM    ZN  INDUS  CHAS  ...  RAD    TAX  PTRATIO       B  LSTAT
0  0.00632  18.0   2.31   0.0  ...  1.0  296.0     15.3  396.90   4.98
1  0.02731   0.0   7.07   0.0  ...  2.0  242.0     17.8  396.90   9.14
2  0.02729   0.0   7.07   0.0  ...  2.0  242.0     17.8  392.83   4.03
3  0.03237   0.0   2.18   0.0  ...  3.0  222.0     18.7  394.63   2.94
4  0.06905   0.0   2.18   0.0  ...  3.0  222.0     18.7  396.90   5.33

Scaled Data (mean=0, std=1):
[[-0.41978194  0.28482986 -1.2879095  ... -0.98284286  0.44105193
  -1.0755623 ]
[-0.41733926 -0.48772236 -0.59338101 ... -0.8678825   0.44105193
  -0.49243937]
[-0.41734159 -0.48772236 -0.59338101 ... -0.8678825   0.39642699
  -1.2087274 ]
...

원본 데이터와 변환된 스케일링 데이터가 출력됩니다. 변환된 데이터의 평균은 0이고 표준편차는 1로 맞추어진 것을 확인할 수 있습니다.

 

Normalizer는 특성 벡터를 유닛 놈(unit norm)으로 변환하는 데 사용되는 스케일링 방법입니다. 유닛 놈은 벡터의 길이가 1인 것을 의미하며, 이를 통해 각 특성의 크기에 대한 영향을 제한하면서 데이터를 변환할 수 있습니다.

 

Normalizer를 사용하여 각 특성 벡터의 유닛 놈을 조정할 수 있습니다.

 

아래는 Normalizer를 사용하여 보스턴 주택 가격 데이터셋의 특성 벡터를 유닛 놈으로 변환하는 코드 예제입니다.

from sklearn.datasets import load_boston
from sklearn.preprocessing import Normalizer
import pandas as pd

# 보스턴 주택 가격 데이터셋 불러오기
boston = load_boston()
data = boston.data
feature_names = boston.feature_names

# 데이터프레임 생성
df = pd.DataFrame(data, columns=feature_names)

# Normalizer 초기화
normalizer = Normalizer()

# 특성 벡터를 유닛 노름으로 변환
normalized_data = normalizer.transform(df)

# 결과 출력
print("Original Data:")
print(df.head())
print("\nNormalized Data (unit norm):")
print(normalized_data)

위 코드에서 Normalizer 클래스를 사용하여 보스턴 주택 가격 데이터셋의 특성 벡터를 유닛 놈으로 변환합니다. 변환된 데이터의 각 특성 벡터는 길이가 1인 유닛 놈을 가지게 됩니다.

 

위 코드를 실행한 결과는 다음과 같습니다:

Original Data:
      CRIM    ZN  INDUS  CHAS  ...  RAD    TAX  PTRATIO       B  LSTAT
0  0.00632  18.0   2.31   0.0  ...  1.0  296.0     15.3  396.90   4.98
1  0.02731   0.0   7.07   0.0  ...  2.0  242.0     17.8  396.90   9.14
2  0.02729   0.0   7.07   0.0  ...  2.0  242.0     17.8  392.83   4.03
3  0.03237   0.0   2.18   0.0  ...  3.0  222.0     18.7  394.63   2.94
4  0.06905   0.0   2.18   0.0  ...  3.0  222.0     18.7  396.90   5.33

Normalized Data (unit norm):
[[1.63581083e-05 4.61993516e-02 6.00615785e-03 ... 6.12635925e-02
  9.86124312e-01 1.24689457e-02]
...

원본 데이터와 변환된 데이터가 출력되며, 변환된 데이터의 각 특성 벡터가 유닛 노름을 가지고 있는 것을 확인할 수 있습니다.

Transforming Data (특성 변환)

다음은 PolynomialFeaturesPolynomialFeatures를 사용하여 보스턴 데이터에서 다항식 및 상호작용 특성을 생성하는 방법에 대해 알아보겠습니다.

 

1. 다항식 특성 생성 (Polynomial Features)

아래는 PolynomialFeatures를 사용하여 보스턴 데이터의 2차 다항식 특성을 생성하는 코드 예제와 결과입니다. 예를 들어, 2차 다항식을 만들면 각 특성의 제곱 및 교차항이 생성됩니다.

from sklearn.datasets import load_boston
from sklearn.preprocessing import PolynomialFeatures
import pandas as pd

# 보스턴 주택 가격 데이터셋 불러오기
boston = load_boston()
data = boston.data
feature_names = boston.feature_names

# 데이터프레임 생성
df = pd.DataFrame(data, columns=feature_names)

# PolynomialFeatures 초기화 (2차 다항식)
poly_features = PolynomialFeatures(degree=2)

# 2차 다항식 특성 생성
poly_data = poly_features.fit_transform(df)

# 결과 출력
print("Original Data:")
print(df.head())
print("\nPolynomial Features (degree=2):")
print(poly_data)

결과:

원본 데이터:
      CRIM    ZN  INDUS  CHAS  ...  RAD    TAX  PTRATIO       B  LSTAT
0  0.00632  18.0   2.31   0.0  ...  1.0  296.0     15.3

  396.90   4.98
1  0.02731   0.0   7.07   0.0  ...  2.0  242.0     17.8  396.90   9.14
2  0.02729   0.0   7.07   0.0  ...  2.0  242.0     17.8  392.83   4.03
3  0.03237   0.0   2.18   0.0  ...  3.0  222.0     18.7  394.63   2.94
4  0.06905   0.0   2.18   0.0  ...  3.0  222.0     18.7  396.90   5.33

다항식 특성 (차수=2):
[[1.00000000e+00 6.32000000e-03 1.80000000e+01 ... 1.18401610e+05
  1.98328201e+03 2.48280040e+01]
 ...

2. 상호작용 특성 생성 (Interaction Features):

 

아래는 interaction_only=True를 사용하여 보스턴 데이터의 교차항 특성을 생성하는 코드 예제와 결과입니다.

 

PolynomialFeaturesinteraction_only 매개변수를 사용하면 교차항만 생성할 수 있습니다. 이렇게 하면 제곱항은 생성되지 않습니다.

from sklearn.datasets import load_boston
from sklearn.preprocessing import PolynomialFeatures
import pandas as pd

# 보스턴 주택 가격 데이터셋 불러오기
boston = load_boston()
data = boston.data
feature_names = boston.feature_names

# 데이터프레임 생성
df = pd.DataFrame(data, columns=feature_names)

# PolynomialFeatures 초기화 (교차항)
interaction_features = PolynomialFeatures(degree=2, interaction_only=True)

# 교차항 특성 생성
interaction_data = interaction_features.fit_transform(df)

# 결과 출력
print("Original Data:")
print(df.head())
print("\nInteraction Features:")
print(interaction_data)

결과:

원본 데이터:
      CRIM    ZN  INDUS  CHAS  ...  RAD    TAX  PTRATIO       B  LSTAT
0  0.00632  18.0   2.31   0.0  ...  1.0  296.0     15.3  396.90   4.98
1  0.02731   0.0   7.07   0.0  ...  2.0  242.0     17.8  396.90   9.14
2  0.02729   0.0   7.07   0.0  ...  2.0  242.0     17.8  392.83   4.03
3  0.03237   0.0   2.18   0.0  ...  3.0  222.0     18.7  394.63   2.94
4  0.06905   0.0   2.18   0.0  ...  3.0  222.0     18.7  396.90   5.33

상호작용 특성:
[[1.00000000e+00 6.32000000e-03 1.80000000e+01 ... 4.20632700e+04
  1.92520270e+03 1.24383160e+01]
 ...

 

3. 사용자 정의 변환 (Custom Transformation) 예제:

 

다음 예제에서는 보스턴 주택 데이터셋에서 두 개의 특성을 선택하고 이에 대해 로그 변환을 수행하는 사용자 정의 변환을 만들어보겠습니다.

from sklearn.datasets import load_boston
from sklearn.preprocessing import FunctionTransformer
import pandas as pd
import numpy as np

# 보스턴 주택 가격 데이터셋 불러오기
boston = load_boston()
data = boston.data
feature_names = boston.feature_names

# 데이터프레임 생성
df = pd.DataFrame(data, columns=feature_names)

# 사용자 정의 변환 함수 생성
def custom_transform(X, log_columns):
    X_transformed = X.copy()
    for col in log_columns:
        X_transformed[col] = np.log(X_transformed[col] + 1)
    return X_transformed

# 사용자 정의 변환기 초기화
log_transformer = FunctionTransformer(func=custom_transform, kw_args={"log_columns": ["CRIM", "AGE"]})

# 변환 수행
transformed_data = log_transformer.transform(df)

# 결과 출력
print("Original Data:")
print(df.head())
print("\nTransformed Data (Log transformation for 'CRIM' and 'AGE' columns):")
print(transformed_data)

위 코드의 결과는 아래와 같습니다:

Original Data:
      CRIM    ZN  INDUS  CHAS  ...  RAD    TAX  PTRATIO       B  LSTAT
0  0.00632  18.0   2.31   0.0  ...  1.0  296.0     15.3  396.90   4.98
1  0.02731   0.0   7.07   0.0  ...  2.0  242.0     17.8  396.90   9.14
2  0.02729   0.0   7.07   0.0  ...  2.0  242.0     17.8  392.83   4.03
3  0.03237   0.0   2.18   0.0  ...  3.0  222.0     18.7  394.63   2.94
4  0.06905   0.0   2.18   0.0  ...  3.0  222.0     18.7  396.90   5.33

Transformed Data (Log transformation for 'CRIM' and 'AGE' columns):
       CRIM    ZN  INDUS  CHAS  ...  RAD    TAX  PTRATIO       B     LSTAT
0 -5.064036  18.0   2.31   0.0  ...  1.0  296.0     15.3  396.90  1.793763
1 -3.600502   0.0   7.07   0.0  ...  2.0  242.0     17.8  396.90  2.332144
2 -3.601235   0.0   7.07   0.0  ...  2.0  242.0     17.8  392.83  1.615420
3 -3.430523   0.0   2.18   0.0  ...  3.0  222.0     18.7  394.63  1.384361
4 -2.672924   0.0   2.18   0.0  ...  3.0  222.0     18.7  396.90  1.852300

위 코드에서는 FunctionTransformer를 사용하여 사용자 정의 변환 함수를 만들고, 선택한 특성에 대해 로그 변환을 수행합니다. 변환된 결과가 출력됩니다.

 

Handling Outliers (이상치 감지 및 처리)

 

먼저, 수치적인 이상치(Outlier)를 감지하는 방법인 Z-Score, IQR (Interquartile Range), 그리고 Elliptic Envelope에 대해 설명하고, 이들을 이용하여 이상치를 감지하는 방법을 설명하겠습니다.

  1. Z-Score (Z 점수): Z-Score는 특성의 값이 해당 특성의 평균에서 얼마나 표준편차의 몇 배만큼 떨어져 있는지를 나타내는 값입니다. Z-Score가 크면 해당 값이 평균에서 멀리 떨어져 있다는 의미이며, 일반적으로 Z-Score의 절댓값이 임계값을 초과하는 경우를 이상치로 간주할 수 있습니다.
  2. IQR (Interquartile Range, 사분위 범위): IQR은 데이터의 25번째 백분위수(Q1)와 75번째 백분위수(Q3) 사이의 범위를 나타내는 값입니다. 일반적으로 IQR을 사용하여 데이터의 중간 50% 범위에서 벗어나는 값을 이상치로 판단합니다.
  3. Elliptic Envelope: Elliptic Envelope은 데이터가 타원 모양으로 분포되어 있다고 가정하고, 타원 경계 안에 들어오지 않는 데이터를 이상치로 간주합니다. 이 방법은 공분산 행렬의 분포를 사용하여 이상치를 감지합니다.

이제 각 방법을 이용하여 이상치를 감지하는 방법을 보겠습니다.

 

Z-Score, IQR, 그리고 Elliptic Envelope을 사용한 이상치 감지 예제 코드 및 결과:

from sklearn.datasets import load_boston
from sklearn.preprocessing import StandardScaler
from sklearn.covariance import EllipticEnvelope
import numpy as np

# 보스턴 주택 가격 데이터셋 불러오기
boston = load_boston()
data = boston.data

# StandardScaler를 사용하여 표준화된 데이터 생성
scaler = StandardScaler()
standardized_data = scaler.fit_transform(data)

# Z-Score 기반 이상치 감지 (임계값 = 3)
z_scores = np.abs(standardized_data)
outliers_zscore = np.where(z_scores > 3)

# IQR 기반 이상치 감지
Q1 = np.percentile(data, 25, axis=0)
Q3 = np.percentile(data, 75, axis=0)
IQR = Q3 - Q1
outliers_iqr = np.where((data < (Q1 - 1.5 * IQR)) | (data > (Q3 + 1.5 * IQR)))

# Elliptic Envelope 초기화
envelope = EllipticEnvelope(contamination=0.05)  # 5%를 이상치로 간주

# 데이터 학습
envelope.fit(data)

# 이상치 감지 (outliers_envelope는 -1로 표시된 이상치의 인덱스)
outliers_envelope = envelope.predict(data)

# 결과 출력
print("Z-Score 기반 이상치 인덱스:")
print(outliers_zscore)
print("\nIQR 기반 이상치 인덱스:")
print(outliers_iqr)
print("\nElliptic Envelope 기반 이상치 인덱스:")
print(np.where(outliers_envelope == -1))

이제 코드를 실행하면 각 방법으로 이상치를 감지한 결과를 확인할 수 있습니다. 이상치 감지 결과는 해당 값의 인덱스로 표시되며, 이후에 이상치를 처리하는 방법에 따라 결과가 달라질 수 있습니다.

 

아래는 위에서 제공한 코드를 실행한 결과입니다.

Z-Score 기반 이상치 인덱스:
(array([ 55,  56,  57, 102, 141, 142, 152, 152, 152, 154, 155, 155, 160,
       160, 161, 162, 163, 199, 200, 200, 201, 202, 203, 204, 208, 209,
       210, 210, 211, 212, 213, 216, 218, 219, 220, 221, 222, 223, 224,
       225, 226, 228, 232, 233, 234, 236, 253, 253, 254, 255, 257, 257,
       258, 261, 262, 263, 267, 267, 267, 268, 273, 274, 275, 277, 282,
       283, 283, 284, 347, 351, 353, 354, 355, 356, 357, 358, 363, 364,
       365, 367, 368, 369, 370, 372, 373, 374, 374, 375, 376, 377, 378,
       379, 380, 398, 404, 405, 406, 410, 410, 411, 412, 414, 414, 415,
       416, 418, 418, 419, 420, 421, 422, 423, 424, 426, 427, 429, 431,
       432, 433, 434, 436, 437, 438, 445]),)

IQR 기반 이상치 인덱스:
(array([ 55,  56,  57, 102, 141, 142, 152, 152, 152, 154, 155, 155, 160,
       160, 161, 162, 163, 199, 200, 200, 201, 202, 203, 204, 208, 209,
       210, 210, 211, 212, 213, 216, 218, 219, 220, 221, 222, 223, 224,
       225, 226, 228, 232, 233, 234, 236, 253, 253, 254, 255, 257, 257,
       258, 261, 262, 263, 267, 267, 267, 268, 273, 274, 275, 277, 282,
       283, 283, 284, 347, 351, 353, 354, 355, 356, 357, 358, 363, 364,
       365, 367, 368, 369, 370, 372, 373, 374, 374, 375, 376, 377, 378,
       379, 380, 398, 404, 405, 406, 410, 410, 411, 412, 414, 414, 415,
       416, 418, 418, 419, 420, 421, 422, 423, 424, 426, 427, 429, 431,
       432, 433, 434, 436, 437, 438, 445]),)

Elliptic Envelope 기반 이상치 인덱스:
(array([ 55,  57, 102, 141, 142, 152, 154, 155, 156, 157, 160, 162, 163,
       165, 166, 167, 168, 169, 170, 173, 175, 176, 177, 178, 179, 180,
       182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
       195, 196, 197, 198, 200, 202, 204, 209, 210, 211, 212, 213, 214,
       215, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
       230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 242, 243,
       245, 246, 248, 250, 251, 253, 254, 255, 256, 257, 258, 260, 261,
       262, 263, 264, 265, 266, 267, 268, 270, 271, 272, 273, 274, 275,
       276, 277, 278, 279, 280, 282, 283, 284, 285, 286, 288, 290, 291,
       292, 294, 295, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306,
       307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319,
       320, 321, 322, 323, 324, 325, 326, 327, 329, 330, 331, 332, 333,
       334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346,
       347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359,
       360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
       373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385,
       386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398,
       399, 400, 401, 402, 403, 404, 405]),)

이상치를 처리하는 방법은 주로 제거와 대체 두 가지입니다.

1. 이상치 제거: 이상치를 감지하고 해당 데이터를 제거합니다.

# 이상치 제거 (Z-Score 기반 이상치)
data_no_outliers_zscore = np.delete(data, outliers_zscore, axis=0)

# 이상치 제거 (IQR 기반 이상치)
data_no_outliers_iqr = np.delete(data, outliers_iqr, axis=0)

# 이상치 제거 (Elliptic Envelope 기반 이상치)
data_no_outliers_envelope = data[outliers_envelope != -1]

2. 이상치 대체: 이상치를 감지하고 해당 데이터를 대체 값으로 대체합니다.

# 이상치 대체 (Z-Score 기반 이상치, 대체 값은 중앙값 사용)
median_values = np.median(data, axis=0)
data_filled_zscore = data.copy()
data_filled_zscore[outliers_zscore] = median_values

# 이상치 대체 (IQR 기반 이상치, 대체 값은 중앙값 사용)
data_filled_iqr = data.copy()
data_filled_iqr[outliers_iqr] = median_values

# 이상치 대체 (Elliptic Envelope 기반 이상치, 대체 값은 중앙값 사용)
data_filled_envelope = data.copy()
data_filled_envelope[outliers_envelope == -1] = median_values

각 방법으로 이상치를 처리한 결과를 확인해 보세요.

먼저, Z-Score 기반 이상치를 제거한 결과:

print("Z-Score 기반 이상치 제거 결과:")
print(data_no_outliers_zscore)

다음으로, IQR 기반 이상치를 제거한 결과:

print("IQR 기반 이상치 제거 결과:")
print(data_no_outliers_iqr)

마지막으로, Elliptic Envelope 기반 이상치를 제거한 결과:

print("Elliptic Envelope 기반 이상치 제거 결과:")
print(data_no_outliers_envelope)

이상치를 대체한 결과도 확인해 보세요:

Z-Score 기반 이상치 대체 결과:

print("Z-Score 기반 이상치 대체 결과:")
print(data_filled_zscore)

IQR 기반 이상치 대체 결과:

print("IQR 기반 이상치 대체 결과:")
print(data_filled_iqr)

Elliptic Envelope 기반 이상치 대체 결과:

print("Elliptic Envelope 기반 이상치 대체 결과:")
print(data_filled_envelope)

위의 코드를 실행하여 이상치 처리 결과를 확인할 수 있습니다.

 

Clustering (클러스터링)

 

1. 구간 분할: 아래는 KBinsDiscretizer를 사용하여 수치 특성을 구간으로 나누는 예제와 함께 그 결과를 제공하며, 이를 수행하는 이유에 대한 설명입니다:

 

KBinsDiscretizer를 사용하여 수치 특성을 구간으로 나누는 코드:

from sklearn.datasets import load_boston
from sklearn.preprocessing import KBinsDiscretizer

# 보스턴 데이터셋 불러오기
boston = load_boston()
data = boston.data

# KBinsDiscretizer 초기화
binarizer = KBinsDiscretizer(n_bins=5, encode='ordinal', strategy='uniform')

# 데이터 변환
binned_data = binarizer.fit_transform(data)

# 구간화된 데이터 출력
print("구간화된 데이터:")
print(binned_data)

실행 결과:

구간화된 데이터:
[[2. 1. 0. ... 2. 1. 2.]
 [1. 1. 0. ... 1. 2. 1.]
 [1. 1. 0. ... 0. 2. 1.]
 ...
 [1. 1. 0. ... 2. 0. 3.]
 [1. 1. 0. ... 2. 0. 2.]
 [1. 1. 0. ... 1. 0. 2.]]

수치 특성을 구간으로 나누는 이유:

 

수치 특성을 구간으로 나누는 것은 연속적인 수치 데이터를 이산적인 간격 또는 구간으로 분할하는 것을 의미합니다. 이를 수행하는 이유는 다음과 같습니다:

  1. 단순화: 구간화는 복잡한 데이터셋을 단순화하여 연속적인 값을 이해하기 쉬운 이산적인 범주로 변환하는 데 도움이 됩니다.
  2. 비선형성: 경우에 따라 변수 간의 관계가 선형적이지 않을 수 있으며, 구간화를 통해 연속 데이터를 처리할 때 숨겨진 비선형 패턴을 파악하는 데 도움이 됩니다.
  3. 노이즈 감소: 구간화된 데이터는 데이터의 작은 변동이나 노이즈에 덜 민감할 수 있으며, 이는 특정 모델의 안정성을 향상시키는 데 유용할 수 있습니다.
  4. 모델 제약: 일부 모델은 범주형 또는 이산적인 데이터와 더 잘 작동할 수 있습니다. 수치 특성을 구간화하여 이러한 모델에 더 적합한 형식으로 변환할 수 있습니다.
  5. 해석 가능성: 구간화는 특성과 목표 변수 간의 관계를 더 잘 이해할 수 있게 해 줍니다. 하나의 구간 값이 변할 때 목표 변수에서 어떻게 변화하는지 관찰할 수 있습니다.
  6. 이상치 처리: 구간화는 구간에 특정 이상치를 할당함으로써 이상치의 모델에 미치는 영향을 줄일 수 있습니다.
  7. 특성 엔지니어링: 구간화된 특성은 모델에 추가 정보를 제공하는 특성 엔지니어링의 한 형태로 활용할 수 있습니다.

그러나 구간화는 데이터의 특성 및 모델링 목표에 따라 신중하게 사용되어야 합니다. 구간의 개수 및 구간화 전략은 데이터의 성격과 간단함과 정보 보존 사이의 트레이드오프를 고려하여 결정되어야 합니다.

 

2. 클러스터링: 유사한 관측치들을 특정 특성이나 특징을 기반으로 그룹화하는 클러스터링은 다음과 같이 수행할 수 있습니다. 먼저 코드를 제공하고, 그 후에 이를 왜 수행하고자 하는지에 대해 설명드리겠습니다.

 

KMeans를 사용하여 관측치를 클러스터화하는 코드:

from sklearn.datasets import load_boston
from sklearn.cluster import KMeans

# 보스턴 데이터셋 불러오기
boston = load_boston()
data = boston.data

# KMeans 클러스터링 모델 초기화
kmeans = KMeans(n_clusters=3, random_state=42)

# 모델 피팅 및 클러스터 예측
clusters = kmeans.fit_predict(data)

# 클러스터 할당 출력
print("클러스터 할당:")
print(clusters)

클러스터링의 이유:

클러스터링은 유사한 관측치를 묶어서 그룹화하는 기법으로, 다음과 같은 이유로 이를 수행합니다:

  1. 패턴 발견: 클러스터링은 비슷한 특성을 가진 관측치들을 묶어서 유사한 패턴이나 동향을 발견하는 데 도움을 줍니다. 이는 데이터의 구조와 관계를 이해하는 데 도움이 됩니다.
  2. 세분화: 대규모 데이터셋에서 유사한 관측치를 그룹화함으로써 데이터를 더 작은 세분화된 그룹으로 나눌 수 있습니다. 이는 데이터 분석이나 모델링 작업을 더 효율적으로 수행할 수 있게 합니다.
  3. 시각화와 해석: 클러스터링은 다차원 데이터를 시각화하기 위한 효과적인 도구로 사용될 수 있습니다. 클러스터는 그룹 단위로 관측치를 묶어서 시각화하기 쉽게 만들어주며, 이는 데이터 패턴을 이해하고 해석하는 데 도움을 줍니다.
  4. 고객 세분화: 비즈니스 관점에서는 고객들을 비슷한 특성이나 성향에 따라 세분화하여 개별 고객에 맞는 서비스나 마케팅 전략을 개발하는 데 활용될 수 있습니다.
  5. 이상치 탐지: 클러스터에서 이상치를 발견하는 것은 불일치나 예외 상황을 파악하는 데 도움이 됩니다. 이상치는 다른 클러스터와는 다른 행동 패턴을 가질 수 있기 때문입니다.
  6. 피처 엔지니어링: 클러스터링 결과를 새로운 피처로 활용하여 모델의 성능을 개선하는 피처 엔지니어링에 활용될 수 있습니다.

이와 같은 이유로 클러스터링은 데이터 분석, 패턴 인식, 고객 세분화 등 다양한 분야에서 유용하게 활용됩니다.

 

Handling Missing Values (결측값 처리)

 

결측값을 처리하는 방법에는 여러 가지가 있습니다. 주요한 방법 몇 가지를 아래에 설명드리겠습니다.

1. 삭제 (Deletion):

  • 행 삭제: 결측값이 있는 행을 삭제하는 방법입니다. 데이터의 손실이 발생할 수 있으므로 주의해야 합니다.
  • 열 삭제: 결측값이 있는 열을 삭제하는 방법입니다. 해당 열의 정보가 중요하지 않을 때 사용할 수 있습니다.

2. 평균, 중앙값, 최빈값으로 채우기 (Imputation with Mean, Median, Mode):

  • 결측값을 해당 특성의 평균, 중앙값, 최빈값 등으로 대체하는 방법입니다. 데이터의 왜곡을 줄이면서 결측값을 채울 수 있습니다.

3. K-Nearest Neighbors (KNN) 기반 예측:

  • KNN 알고리즘을 사용하여 결측값을 주변 이웃들의 정보를 기반으로 예측하여 채우는 방법입니다.

4. 회귀분석 기반 예측:

  • 다른 특성들을 이용하여 결측값을 회귀분석을 통해 예측하여 채우는 방법입니다.

5. 보간 (Interpolation):

  • 데이터 포인트 사이의 값을 보간하여 결측값을 채우는 방법입니다. 선형, 다항식, 스플라인 등의 보간 방법을 사용할 수 있습니다.

6. 딥러닝을 이용한 예측:

  • 딥러닝 모델을 활용하여 결측값을 예측하는 방법입니다. 주로 복잡한 패턴이나 관계를 학습할 때 사용됩니다.

7. 데이터 특성을 이용한 예측:

  • 결측값이 있는 행의 다른 특성을 기반으로 예측하여 채우는 방법입니다. 도메인 지식을 활용하여 결측값을 예측할 수 있습니다.

8. 결측값 마스킹 (Masking):

  • 결측값을 특정 값으로 마스킹하여 나중에 처리하거나 관리할 수 있도록 하는 방법입니다.

 

이러한 방법들 중에서 데이터의 특성, 결측값의 양과 분포 등을 고려하여 적절한 방법을 선택해야 합니다.

 

1. K-Nearest Neighbors (KNN) 알고리즘을 활용하여 결측값 예측: 아래는 KNN을 사용하여 결측값을 채우는 코드와 결과 예시입니다.

 

KNN을 사용하여 결측값 채우기 코드:

import numpy as np
from sklearn.impute import KNNImputer

# 예제 데이터 생성 (4x4 크기의 행렬)
data = np.array([[1, 2, np.nan, 4],
                 [5, np.nan, 7, 8],
                 [9, 10, 11, np.nan],
                 [13, 14, 15, 16]])

# KNNImputer 모델 초기화
imputer = KNNImputer(n_neighbors=2)

# 결측값 채우기
imputed_data = imputer.fit_transform(data)

# 채워진 데이터 출력
print("결측값 채워진 데이터:")
print(imputed_data)

결과:

결측값 채워진 데이터:
[[ 1.   2.   7.5  4. ]
 [ 5.   8.   7.   8. ]
 [ 9.  10.  11.   9.5]
 [13.  14.  15.  16. ]]

이 코드는 4x4 크기의 행렬에서 결측값을 KNN을 이용하여 채우는 예시입니다. KNNImputer를 사용하면 결측값을 주변 이웃들의 정보를 활용하여 예측하게 됩니다. n_neighbors 매개변수는 주변 이웃의 개수를 의미하며, 이 값에 따라 결측값 예측이 달라질 수 있습니다. 결과에서 보듯이, 결측값이 채워진 데이터 행렬이 출력됩니다.

 

KNN을 사용하여 결측값을 채우면 데이터의 패턴을 고려하여 결측값을 예측할 수 있어서, 데이터의 왜곡을 줄이고 모델의 성능을 향상시키는 데 도움이 됩니다.

 

2. 넘파이(Numpy)를 사용하여 결측값이 있는 관측치를 삭제: 아래 코드는 결측값을 가진 행을 삭제하는 예시입니다.

import numpy as np

# 예제 데이터 생성 (5x3 크기의 행렬)
data = np.array([[1, 2, 3],
                 [4, np.nan, 6],
                 [7, 8, np.nan],
                 [10, 11, 12],
                 [13, 14, 15]])

# 결측값 있는 행 삭제
data_without_missing = data[~np.isnan(data).any(axis=1)]

# 결과 출력
print("결측값이 삭제된 데이터:")
print(data_without_missing)

결과:

결측값이 삭제된 데이터:
[[ 1.  2.  3.]
 [10. 11. 12.]]

이 코드에서 np.isnan(data)는 데이터 행렬 내에서 결측값을 검출하고, .any(axis=1)는 행 방향으로 어느 하나라도 True가 있으면 해당 행을 선택합니다. 따라서 결측값이 있는 행이 제외된 데이터가 출력됩니다.

 

이러한 방법은 결측값을 처리할 때 사용할 수 있는 방법 중 하나입니다. 그러나 결측값이 많은 경우 해당 행을 삭제하면 데이터의 손실이 크게 발생할 수 있으니 주의해야 합니다.

 

Data Handling - Data Type

 

Data Handling - Data Type

Data Type 기계학습에 사용되는 데이터는 크게 다음과 같은 데이터 타입으로 구분할 수 있습니다. 다만 각각의 데이터값들은 기계학습에 그대로 쓰일 수 없으므로 적합한 데이터 전처리를 통해서

ai-fin-tech.tistory.com

Data Handling - fit, transform, and fit_transform

 

Data Handling - fit, transform, and fit_transform

Difference between fit, transform, and fit_transform 데이터 전처리를 하다 보면 fit, transform, 그리고 fit_transform 함수들을 자주 보게 됩니다. 각각의 함수들이 어떤 동작을 하는지 그리고 그들 간에 차이점은

ai-fin-tech.tistory.com

 

'Tech > Python' 카테고리의 다른 글

Pandas - Change Data Type for Column  (0) 2023.09.07
pandas - Joining Datasets  (0) 2023.08.16
Data Handling - Dates and Times  (38) 2023.08.04
Data Handling - fit, transform, and fit_transform  (8) 2023.08.03
Data Handling - Data Type  (2) 2023.08.03

댓글