jyamethyst21 님의 블로그

머신러닝 & 딥러닝 본문

보안 & IT 지식 🌺

머신러닝 & 딥러닝

jyamethyst21 2026. 1. 9. 23:59

결측치 처리

1) 결측치 제거

- 데이터셋에서 특정 값이 누락된 상태

- 결측치가 데이터셋에서 차지하는 비율이 매우 적을 때, 해당 열이나 행이 분석에 영향 주지 않을 때

- 방법 : 열 제거, 행 제거

import pandas as pd

# 데이터프레임 생성
data = {'Name': ['Alice', 'Bob', None],
'Age': [25, None, 30],
'Score': [85, 90, None]}
df = pd.DataFrame(data)

# 결측치가 있는 행 제거
df_no_missing_rows = df.dropna()

# 결측치가 있는 열 제거
df_no_missing_cols = df.dropna(axis=1)

 

2) 결측치 대체

- 데이터의 양이 적거나, 결측치가 무작정 삭제되면 데이터 손실이 너무 클 때

- 방법 : 고정 값 대체, 특정 값으로 결측치 채움, 통계 기반 대체, 예측 기반 대체(머신러닝 활용)

import pandas as pd

# 데이터프레임 생성
data = {'Name': ['Alice', 'Bob', None],
'Age': [25, None, 30],
'Score': [85, 90, None]}
df = pd.DataFrame(data)

# 평균으로 대체
df['Age'] = df['Age'].fillna(df['Age'].mean())

# 중간값으로 대체
df['Score'] = df['Score'].fillna(df['Score'].median())

# 최빈값으로 대체
df['Name'] = df['Name'].fillna(df['Name'].mode()[0])

이상치 처리

1) 결측치 제거

- 데이터셋에서 다른 값과 크게 동떨어져 있는 값

- IQR 방법과 Z-SCORE 방법 존재

# 1. IQR
# IQR은 데이터의 중간 50%를 포함하는 범위를 이용해 이상치를 탐지하는 방법
# 비대칭 분포 데이터에 적합, 극단값에 영향을 덜 받음.
# Q1 (1사분위수): 하위 25%의 값, Q3 (3사분위수): 상위 75%의 값, IQR: 𝐼𝑄𝑅=𝑄3−𝑄1
# 이상치 기준 : 아래쪽(𝑄1-1.5×𝐼𝑄𝑅)보다 작은값, 위쪽(𝑄3+1.5×𝐼𝑄𝑅) 보다 큰 값

import pandas as pd

# 예제 데이터
data = {'Scores': [70, 75, 80, 85, 90, 150]}
df = pd.DataFrame(data)

# IQR 계산
Q1 = df['Scores'].quantile(0.25) # 1사분위수
Q3 = df['Scores'].quantile(0.75) # 3사분위수
IQR = Q3 - Q1

# 이상치 기준
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 이상치 확인
outliers = df[(df['Scores'] < lower_bound) | (df['Scores'] >
upper_bound)]

# 이상치 제거
#df = df[(df['Scores'] >= lower_bound) & (df['Scores'] <=
upper_bound)]

#이상치 변경
df.loc[df['Scores'] < lower_bound, 'Scores'] = lower_bound
df.loc[df['Scores'] > upper_bound, 'Scores'] = upper_bound

중복 데이터 처리

1) 중복 데이터

- 데이터셋에서 동일한 행이 반복적으로 나타나는 것

# pandas 중복 데이터 확인 및 제거

import pandas as pd

# 예제 데이터
data = {'Name': ['Alice', 'Bob', 'Alice', 'Charlie', 'Bob'],
'Age': [25, 30, 25, 35, 30],
'Score': [85, 90, 85, 95, 90]}
df = pd.DataFrame(data)

# DataFrame 내 중복된 행 확인
print(df.duplicated()) # 각 행이 이전에 등장한 행과 중복되는지 여부를 Boolean 값으로 출력

# 전체 중복 행 제거 (모든 열 값이 동일한 경우)
df_no_duplicates = df.drop_duplicates(keep='first') # 기본값은 keep='first': 첫 번째 중복은 남기고 나머지는 제거

# 특정 열('Name') 기준으로 중복 행 제거
df_no_duplicates_by_name = df.drop_duplicates(subset=['Name']) # 이름이 같은 경우, 첫 번째만 남기고 제거

# 특정 열('Name') 기준 중복 제거 + 마지막 항목을 남기고 이전 항목 제거
df_no_duplicates_by_name_last = df.drop_duplicates(subset=['Name'], keep='last') # 마지막 중복 항목을 유지

# 특정 열('Name') 기준으로 완전한 중복 제거 (중복된 모든 항목 삭제)
df_no_duplicates_by_name_all = df.drop_duplicates(subset=['Name'], keep=False) # 중복된 항목 전부 제거

 

데이터 변환 및 스케일링

1. 데이터 변환 (로그 변환, 스퀘어 루트 변환)

- 데이터의 분포를 변화시켜 분석이나 모델링에 유리한 형태로 만드는 과정

 

가) 로그 변환

- 데이터 값에 로그를 취하는 방법으로, 데이터 값이 매우 크거나 몇 개의 값이 지나치게 크고 나머지는 작은 경우 사용됨

- 오른쪽으로 치우진 분포를 다룰 때 효과적이며 로그 변환 시 큰 값은 축소되고, 작은 값은 상대적으로 커져 데이터 분포를 평탄하게 만들어줌

- 0이나 음수 존재 시 계산 불가하므로 변환 전 값에 작은 상수(1)을 더해야 함

 

나) 스퀘어 루트 변환

- 데이터의 제곱근을 구하는 방법으로 로그 변환보다는 덜 극단적인 방법

- 데이터의 크기를 축소하거나 오른쪽 치우짐을 완화하는데 사용

- 음수 값에 사용 불가

- 로그 변환은 매우 큰값을 다룰 때 효과적이며 스퀘어 루트 변환은 큰 값과 작은 값의 균형을 맞추는데 유용

 

2. 데이터 스케일링 (표준화, 정규화)

- 데이터 스케일링은 데이터의 값 범위를 조정하는 과정

- 머신러닝 모델이 데이터의 크기 차이에 영향을 덜 받게 하기 위해 중요

 

가) 표준화

- 데이터의 값 평균을 0으로 표준편차를 1로 만드는 방법

- 데이터를 똑같은 기준선에 맞춰 공정하게 비교하게 해주는 과정

- 평균 : 데이터의 중심값, 표준편차 : 데이터가 평균에서 얼마나 떨어져있는지 측정

- 데이터가 정규 분포를 따르지 않더라도 표준화 적용이 가능하지만, 분포의 왜도는 남아있을 수 있음

 

나) 정규화

- 데이터를 0과 1 사이로 변환하는 방법

- 값의 크기를 줄이고, 데이터를 일정한 스케일로 맞춤

- 데이터가 일정 범위 내에 있어 스케일에 민감한 알고리즘(신경망, 회귀 등)에 적합

- 이상치의 영향을 줄이는 데도 유용함- 데이터에 이상치가 있을 경우, 최대값과 최소값이 크게 왜곡(데이터 스케일 전 이상치에 대한 처리 선행 필수)

import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler
import matplotlib.pyplot as plt

# 데이터 생성
data = pd.DataFrame({'Original': [50, 80, 90, 100, 60]})

# 표준화
scaler_standard = StandardScaler()
data['Standardized'] =
scaler_standard.fit_transform(data[['Original']])

# 정규화
scaler_minmax = MinMaxScaler()
data['Normalized'] = scaler_minmax.fit_transform(data[['Original']])

# 데이터 확인
print(data)

# 데이터 시각화
plt.figure(figsize=(10, 5))
plt.plot(data['Original'], label='Original Data', marker='o')
plt.plot(data['Standardized'], label='Standardized Data', marker='o')
plt.plot(data['Normalized'], label='Normalized Data', marker='o')
plt.legend()
plt.title('Standardization vs Normalization')
plt.xlabel('Index')
plt.ylabel('Value')
plt.show()

범주형 데이터 처리

1. 범주형 데이터

- 수치가 아닌 텍스트 데이터처럼 특정 범주를 나타내는 데이터

- 머신러닝 알고리즘은 숫자 데이터를 처리하기 때문에, 범주형 데이터를 숫자로 변환해야 함

- 레이블 인코딩과 원-핫 인코딩 방법 존재

 

가) 레이블 인코딩

- 범주형 데이터를 정수로 매핑하여 각 범주를 고유한 숫자로 변환하는 방법

- 데이터의 범주마다 고유한 번호 부여(예: '사과' -> 0, '배' -> 1, '포도'->2)

- 예제: 과일 데이터 ['사과','배','포도','사과'] -> 결과: [0,1,2,0]

- 간단하고 직관적이며 메모리 적게 사용

- 그러나 범주의 순서가 없는데도 숫자가 순서를 암시할 수 있음(사과(0)가 배(1)보다 더 작거나 낮다는 의미를 부여할 위험이 있음)- 범주가 순서형 데이터인 경우 적합함(예: 낮음, 보통, 높음)

 

나) 원-핫 인코딩- 범주형 데이터를 이진 벡터로 변환- 각 범주마다 별도의 열을 만들고, 해당 범주에만 1을 표시하고 나머지는 0으로 표시4- 예제: 과일 데이터 ['사과','배','포도','사과'] -> 사과[1,0,0], 배[0,1,0], 포도[0,0,1]- 결과: 

- 숫자가 범주의 순서를 암시하지 않으므로, 레이블 인코딩의 단점을 극복

- 고차원 문제: 범주의 수가 많아질수록 많은 열이 생성되어 메모리 소모가 큼

- 범주가 순서가 없는 데이터(예:사과, 배, 포도)인 경우 적합함

import pandas as pd
from sklearn.preprocessing import LabelEncoder, OneHotEncoder

# 데이터 생성
data = pd.DataFrame({'Fruits': ['사과', '배', '포도', '사과', '포도']})

# Step 1: 레이블 인코딩
label_encoder = LabelEncoder()
data['Label Encoding'] = label_encoder.fit_transform(data['Fruits'])

# Step 2: 원-핫 인코딩 (OneHotEncoder 사용, sparse_output=False로 개선)
one_hot_encoder = OneHotEncoder(sparse_output=False)
one_hot_encoded = one_hot_encoder.fit_transform(data[['Label Encoding']])

# Step 3: 결과를 DataFrame으로 변환
one_hot_columns = one_hot_encoder.get_feature_names_out()
one_hot_df = pd.DataFrame(one_hot_encoded, columns=one_hot_columns)

# Step 4: 원래 데이터에 추가
data = pd.concat([data, one_hot_df], axis=1)

# 출력
print(data)

데이터 통합 및 조인

1. merge

- 기준 열을 기반으로 데이터 합침

- inner join(교집합), outer join(합집합), left join(왼쪽 데이터프레임값 모두 유지), right join(오른쪽 데이터프레임값 모두 유지)

# merge

# 고객 정보 데이터프레임
customers = pd.DataFrame({
'customer_id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Charlie']
})
# 주문 정보 데이터프레임
orders = pd.DataFrame({
'order_id': [101, 102, 103],
'customer_id': [1, 2, 4],
'product': ['Laptop', 'Tablet', 'Smartphone']
})

 

# 공통된 customer_id로 데이터를 병합 : Ineer Join
result1 = pd.merge(customers, orders, on='customer_id', how='inner')
print(result1)
print('_'*70)
result10 = pd.merge(customers, orders, how='cross')
print(result10)

2. concat

- 데이터 방향으로 쌓기, 데이터를 방향으로 단순히 이어붙임

- 기준 열 없이 데이터를 추가하고 싶을 때 유용

- axis = 0 : 행 방향으로(위아래) 쌓기 , axis = 1 : 열 방향으로(왼쪽오른쪽) 쌓기

import pandas as pd
# 1월 매출 데이터
sales_jan = pd.DataFrame({
'month': ['January', 'January', 'January'],
'product': ['Laptop', 'Tablet', 'Smartphone'],
'sales': [100, 150, 200]
})
# 2월 매출 데이터
sales_feb = pd.DataFrame({
'month': ['February', 'February', 'February'],
'product': ['Laptop', 'Tablet', 'Smartphone'],
'sales': [120, 160, 220]
})
# Row-wise Concatenation (1월과 2월 데이터를 이어붙임)
sales_combined = pd.concat([sales_jan, sales_feb], axis=0)
# 결과 출력
print(sales_combined)

 

'보안 & IT 지식 🌺' 카테고리의 다른 글

머신러닝 & 딥러닝  (0) 2026.01.13
머신러닝 & 딥러닝  (0) 2026.01.12
머신러닝 & 딥러닝  (0) 2026.01.08
머신러닝 & 딥러닝  (0) 2026.01.07
파이썬 기본 문법  (0) 2026.01.06