๐Ÿ›ธ ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ (Python & R)

okorionยท2025๋…„ 10์›” 29์ผ
post-thumbnail

1๏ธโƒฃ ๋จธ์‹ ๋Ÿฌ๋‹์˜ ์ฒซ ๋‹จ๊ณ„ โ€” ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ๋ž€?

๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์€ ์•Œ๊ณ ๋ฆฌ์ฆ˜๋ณด๋‹ค ๋ฐ์ดํ„ฐ ํ’ˆ์งˆ์— ๋” ์ขŒ์šฐ๋œ๋‹ค.
โ€œGarbage in, garbage outโ€ โ€” ์ „์ฒ˜๋ฆฌ๊ฐ€ ์—‰๋ง์ด๋ฉด ์•„๋ฌด๋ฆฌ ์ข‹์€ ๋ชจ๋ธ๋„ ์“ธ๋ชจ์—†๋‹ค.

๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ(Data Preprocessing)๋Š” ์›์‹œ(raw) ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋ธ์ด ํ•™์Šตํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋งŒ๋“œ๋Š” ๋‹จ๊ณ„๋‹ค.
์ด ๊ฐ•์˜์—์„œ๋Š” Python๊ณผ R์„ ๋ณ‘ํ–‰ํ•ด ๋‹ค์Œ ๊ณผ์ •์„ ํ•™์Šตํ•œ๋‹ค.

์ฃผ์š” ๋‹จ๊ณ„ํ•ต์‹ฌ ๊ฐœ๋…์˜ˆ์‹œ
๊ฒฐ์ธก์น˜ ์ฒ˜๋ฆฌํ‰๊ท /์ค‘์•™๊ฐ’ ๋Œ€์ฒด, ์‚ญ์ œ๋‚˜์ด ์ปฌ๋Ÿผ์— ๊ฒฐ์ธก์น˜๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ํ‰๊ท ๊ฐ’์œผ๋กœ ๋Œ€์ฒด
๋ฒ”์ฃผํ˜• ์ธ์ฝ”๋”ฉ์ˆซ์žํ˜• ๋ณ€ํ™˜โ€œFranceโ€, โ€œGermanyโ€ โ†’ [1, 2]
๋ฐ์ดํ„ฐ ๋ถ„๋ฆฌTrain/Test ๋ถ„ํ• 80:20 ๋น„์œจ๋กœ ํ•™์Šต์šฉ๊ณผ ๊ฒ€์ฆ์šฉ ๋ฐ์ดํ„ฐ ๋ถ„๋ฆฌ
์Šค์ผ€์ผ๋งํ‘œ์ค€ํ™”(Standardization) / ์ •๊ทœํ™”(Normalization)ํ‚ค(cm)์™€ ๋ชธ๋ฌด๊ฒŒ(kg) ๋‹จ์œ„์ฐจ ์ œ๊ฑฐ

์ด ๊ณผ์ •์€ ๋ชจ๋“  ๋จธ์‹ ๋Ÿฌ๋‹ ํŒŒ์ดํ”„๋ผ์ธ์˜ ๊ธฐ๋ฐ˜์ด๋‹ค.


2๏ธโƒฃ ๋จธ์‹ ๋Ÿฌ๋‹ ํ”„๋กœ์„ธ์Šค ๊ฐœ์š”

๐Ÿ’ก ์ „์ฒด ํ๋ฆ„

  1. ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ (CSV, SQL, API ๋“ฑ)
  2. ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ (๊ฒฐ์ธก์น˜, ์ธ์ฝ”๋”ฉ, ์Šค์ผ€์ผ๋ง)
  3. ๋ชจ๋ธ ํ•™์Šต (ํšŒ๊ท€, ๋ถ„๋ฅ˜ ๋“ฑ)
  4. ๋ชจ๋ธ ํ‰๊ฐ€ (์ •ํ™•๋„, RMSE ๋“ฑ)
  5. ์˜ˆ์ธก ๋ฐ ๊ฐœ์„ 

์ด ์ค‘ 2๋‹จ๊ณ„ ์ „์ฒ˜๋ฆฌ๋Š” ๋‚˜๋จธ์ง€ ๊ณผ์ •์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ํ•ต์‹ฌ ๋‹จ๊ณ„๋‹ค.


3๏ธโƒฃ ๋ฐ์ดํ„ฐ ์„ธํŠธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

์‹ค์Šต์—์„œ๋Š” Pandas์™€ NumPy๋ฅผ ์‚ฌ์šฉํ•ด CSV ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

import numpy as np
import pandas as pd

dataset = pd.read_csv('Data.csv')
X = dataset.iloc[:, :-1].values   # ๋…๋ฆฝ๋ณ€์ˆ˜
y = dataset.iloc[:, -1].values    # ์ข…์†๋ณ€์ˆ˜

๐Ÿ’ก .iloc[:, :-1] โ†’ ๋งˆ์ง€๋ง‰ ์—ด์„ ์ œ์™ธํ•œ ์ „์ฒด ์—ด ์„ ํƒ
๐Ÿ’ก .iloc[:, -1] โ†’ ๋งˆ์ง€๋ง‰ ์—ด(๊ฒฐ๊ณผ ๋ณ€์ˆ˜) ์„ ํƒ

๐Ÿงช ์‹ค์Šต ํ๋ฆ„

  • CSV ํŒŒ์ผ์„ Google Colab ํ™˜๊ฒฝ์—์„œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
  • Python๊ณผ R์—์„œ ๊ฐ๊ฐ read.csv()์™€ pd.read_csv() ๋น„๊ต
  • ๋ฐ์ดํ„ฐ๋ฅผ ํ…Œ์ด๋ธ” ํ˜•ํƒœ๋กœ ํ™•์ธํ•˜๊ณ  ์ด์ƒ์น˜ยท๊ฒฐ์ธก์น˜ ํƒ์ƒ‰

4๏ธโƒฃ ๊ฒฐ์ธก์น˜(Missing Data) ์ฒ˜๋ฆฌ

๋ฐ์ดํ„ฐ์—๋Š” ์ข…์ข… ๊ฐ’์ด ๋น„์–ด ์žˆ๋Š” ์…€(NA, NaN)์ด ์กด์žฌํ•œ๋‹ค.
์ด๋Œ€๋กœ ๋ชจ๋ธ์— ๋„ฃ์œผ๋ฉด ํ•™์Šต์ด ์‹คํŒจํ•œ๋‹ค.

โœ… ๋ฐฉ๋ฒ• 1: ์‚ญ์ œ

dataset.dropna(inplace=True)

๋‹จ์ : ์ •๋ณด ์†์‹ค์ด ํผ

โœ… ๋ฐฉ๋ฒ• 2: ๋Œ€์ฒด (Imputation)

from sklearn.impute import SimpleImputer
imputer = SimpleImputer(missing_values=np.nan, strategy='mean')
imputer.fit(X[:, 1:3])
X[:, 1:3] = imputer.transform(X[:, 1:3])
์ „๋žต์„ค๋ช…์˜ˆ์‹œ
meanํ‰๊ท ์œผ๋กœ ๋Œ€์ฒด์ˆ˜์น˜ํ˜• ์ปฌ๋Ÿผ
median์ค‘์•™๊ฐ’์œผ๋กœ ๋Œ€์ฒด์ด์ƒ์น˜๊ฐ€ ๋งŽ์€ ๊ฒฝ์šฐ
most_frequent์ตœ๋นˆ๊ฐ’์œผ๋กœ ๋Œ€์ฒด๋ฒ”์ฃผํ˜• ๋ฐ์ดํ„ฐ

R์—์„œ๋Š” na.omit(), mutate() + ifelse(is.na())๋กœ ์ฒ˜๋ฆฌ.


5๏ธโƒฃ ๋ฒ”์ฃผํ˜• ๋ฐ์ดํ„ฐ ์ธ์ฝ”๋”ฉ (Categorical Encoding)

๋ชจ๋ธ์€ ์ˆซ์ž๋งŒ ์ธ์‹ํ•˜๋ฏ€๋กœ, ๋ฌธ์ž์—ด๋กœ ๋œ ๋ฒ”์ฃผํ˜• ๋ณ€์ˆ˜๋ฅผ ์ˆซ์ž๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.

๐Ÿ“˜ 1๋‹จ๊ณ„: Label Encoding

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
X[:, 0] = le.fit_transform(X[:, 0])

์˜ˆ:
["France", "Germany", "Spain"] โ†’ [0, 1, 2]

๋‹จ์ : ์ˆซ์ž๊ฐ€ ํฌ๋‹ค๊ณ  ์ˆœ์„œ ์˜๋ฏธ๊ฐ€ ์ƒ๊น€ โ†’ ํšŒ๊ท€๋ชจ๋ธ์— ๋ถ€์ ์ ˆ


๐Ÿ“˜ 2๋‹จ๊ณ„: One-Hot Encoding

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder

ct = ColumnTransformer(transformers=[('encoder', OneHotEncoder(), [0])], remainder='passthrough')
X = np.array(ct.fit_transform(X))

๊ฒฐ๊ณผ:

France  Germany  Spain
1       0        0
0       1        0
0       0        1

๐Ÿ’ก ์ˆœ์„œ ๋Œ€์‹  ๋”๋ฏธ ๋ณ€์ˆ˜(dummy variable)๋กœ ๊ตฌ๋ถ„
๐Ÿ’ก ํšŒ๊ท€ ๋ชจ๋ธ์—์„œ๋Š” ์ฒซ ์—ด(๊ธฐ์ค€๊ฐ’)์„ ์‚ญ์ œํ•ด ๋‹ค์ค‘๊ณต์„ ์„ฑ ๋ฐฉ์ง€


6๏ธโƒฃ ๋ฐ์ดํ„ฐ ๋ถ„๋ฆฌ (Train/Test Split)

๋ชจ๋ธ์˜ ์ผ๋ฐ˜ํ™” ์„ฑ๋Šฅ์„ ํ‰๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„๋ฆฌํ•œ๋‹ค.

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=1
)
์šฉ๋„๋น„์œจ์„ค๋ช…
X_train, y_train80%๋ชจ๋ธ ํ•™์Šต
X_test, y_test20%๋ชจ๋ธ ๊ฒ€์ฆ

๐Ÿ’ก random_state๋ฅผ ๊ณ ์ •ํ•ด ์žฌํ˜„์„ฑ ํ™•๋ณด
R์—์„œ๋Š” sample.split() ํ•จ์ˆ˜๋กœ ๋™์ผํ•œ ์ž‘์—… ์ˆ˜ํ–‰.


7๏ธโƒฃ ํŠน์„ฑ ์Šค์ผ€์ผ๋ง (Feature Scaling)

๊ฐ ํŠน์„ฑ์ด ๋‹ค๋ฅธ ๋‹จ์œ„๋ฅผ ๊ฐ€์ง€๋ฉด ๋ชจ๋ธ์ด ํŠน์ • ๋ณ€์ˆ˜์— ํŽธํ–ฅ๋œ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, โ€œ์—ฐ๋ด‰(๋งŒ์›)โ€์€ โ€œ๋‚˜์ด(์„ธ)โ€๋ณด๋‹ค ๊ฐ’์ด ํ›จ์”ฌ ์ปค์„œ ํ•™์Šต์— ์˜ํ–ฅ์„ ๊ณผ๋„ํ•˜๊ฒŒ ๋ฏธ์นœ๋‹ค.

โœ… ํ‘œ์ค€ํ™”(Standardization)

from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train[:, 3:] = sc.fit_transform(X_train[:, 3:])
X_test[:, 3:] = sc.transform(X_test[:, 3:])

๊ณต์‹:

z=xโˆ’ฮผฯƒz = \frac{x - \mu}{\sigma}

โ†’ ํ‰๊ท  0, ํ‘œ์ค€ํŽธ์ฐจ 1๋กœ ๋ณ€ํ™˜

โœ… ์ •๊ทœํ™”(Normalization)

๋ชจ๋“  ๊ฐ’์„ 0~1 ์‚ฌ์ด๋กœ ๋งž์ถค.

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X)

ํŠธ๋ฆฌ ๊ธฐ๋ฐ˜ ๋ชจ๋ธ(Decision Tree, Random Forest)์€ ์Šค์ผ€์ผ๋ง ๋ถˆํ•„์š”
๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜(KNN, SVM, PCA ๋“ฑ)์€ ํ•„์ˆ˜


8๏ธโƒฃ Python vs R ๋น„๊ต ์ •๋ฆฌ

๋‹จ๊ณ„PythonR
๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐpd.read_csv()read.csv()
๊ฒฐ์ธก์น˜ ์ฒ˜๋ฆฌSimpleImputermutate() + ifelse()
์ธ์ฝ”๋”ฉOneHotEncoderfactor()
๋ฐ์ดํ„ฐ ๋ถ„๋ฆฌtrain_test_split()sample.split()
์Šค์ผ€์ผ๋งStandardScalerscale()

9๏ธโƒฃ ์ „์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ ์™„์„ฑ

๐Ÿงฉ ํ…œํ”Œ๋ฆฟ ์ฝ”๋“œ

# Step 1. Import
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer

# Step 2. Load dataset
dataset = pd.read_csv('Data.csv')
X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, -1].values

# Step 3. Handle missing values
imputer = SimpleImputer(strategy='mean')
X[:, 1:3] = imputer.fit_transform(X[:, 1:3])

# Step 4. Encode categorical data
ct = ColumnTransformer([('encoder', OneHotEncoder(), [0])], remainder='passthrough')
X = np.array(ct.fit_transform(X))

# Step 5. Split dataset
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)

# Step 6. Feature scaling
sc = StandardScaler()
X_train[:, 3:] = sc.fit_transform(X_train[:, 3:])
X_test[:, 3:] = sc.transform(X_test[:, 3:])

์ด ํ…œํ”Œ๋ฆฟ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์–ด๋–ค ๋ฐ์ดํ„ฐ์…‹์ด๋ผ๋„ ๊ฐ„๋‹จํžˆ ์ „์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.


๐Ÿ”Ÿ ๊ฒฐ๋ก 

๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ๋Š” ๋จธ์‹ ๋Ÿฌ๋‹์˜ ์ถœ๋ฐœ์ ์ด์ž ํ•ต์‹ฌ ๋‹จ๊ณ„๋‹ค.
๊ฒฐ์ธก์น˜, ์ธ์ฝ”๋”ฉ, ๋ถ„๋ฆฌ, ์Šค์ผ€์ผ๋ง์„ ์ž๋™ํ™”ํ•˜๋ฉด ๋ชจ๋ธ ํ•™์Šต ๊ณผ์ •์ด ์•ˆ์ •ํ™”๋˜๊ณ , ์žฌํ˜„์„ฑ ์žˆ๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“Š ํ•ต์‹ฌ ์š”์•ฝ

๋‹จ๊ณ„์ฃผ์š” ๋ชฉ์ Python ๋„๊ตฌ
๊ฒฐ์ธก์น˜ ์ฒ˜๋ฆฌ๋ถˆ์™„์ „ํ•œ ๋ฐ์ดํ„ฐ ๋ณด์™„SimpleImputer
์ธ์ฝ”๋”ฉ๋ฒ”์ฃผํ˜• โ†’ ์ˆซ์žํ˜• ๋ณ€ํ™˜OneHotEncoder
๋ฐ์ดํ„ฐ ๋ถ„๋ฆฌ์ผ๋ฐ˜ํ™” ํ‰๊ฐ€train_test_split
์Šค์ผ€์ผ๋ง๋ณ€์ˆ˜ ๋‹จ์œ„ ์ •๊ทœํ™”StandardScaler
profile
okorion's Tech Study Blog.

0๊ฐœ์˜ ๋Œ“๊ธ€