캐글의 [Avocado Prices] 데이터셋을 이용해서 아보카도 가격을 예측하는 모델을 만들어봤다.

 

https://www.kaggle.com/datasets/neuromusic/avocado-prices

 

Avocado Prices

Historical data on avocado prices and sales volume in multiple US markets

www.kaggle.com

 

 

데이터 로드 및 확인

import pandas as pd
import numpy as np

import warnings

warnings.filterwarnings('ignore', category=UserWarning)

df = pd.read_csv("./data/avocado.csv")
df.head()

 

df.info()

 

df.describe()

 

df["type"].value_counts()

 

df["year"].value_counts()

 

 

데이터 전처리

df_prep = df.copy()
df_prep["Date2"] = pd.to_datetime(df_prep["Date"])

 

# Date 컬럼의 연도와 year 가 모두 같은지 확인
# 만약 모두 같다면 Date 에서 연도는 추출할 필요 없음
# 확인결과 모두 같음 - 연도 추출할 필요 없음
df_prep[df_prep["Date2"].dt.year != df_prep["year"]][["Date2", "year"]]

 

# Total Bags 값이 Small Bags + Large Bags + XLarge Bags 와 같은지 확인
# 같다면 Total Bags 값은 불필요함
# 확인결과 오차가 있긴 하지만 크지 않으므로 해당 컬럼은 삭제하기로 결정
df_prep["Total Bags2"] = df_prep["Small Bags"] + df_prep["Large Bags"] + df_prep["XLarge Bags"]
# 소수점 계산으로 약간의 오차가 있을 수 있으므로 isclose를 이용해 비슷한지 여부를 확인
are_close = np.isclose(df_prep["Total Bags"], df_prep["Total Bags2"])
df_prep[~are_close][["Total Bags", "Total Bags2"]]

 

# Total Volume 값이 4046 + 4225 + 4770 과 같은지 확인
# 같다면 Total Volume 값은 불필요함
df_prep["Total Volume2"] = df_prep["4046"] + df_prep["4225"] + df_prep["4770"]
# 소수점 계산으로 약간의 오차가 있을 수 있으므로 isclose를 이용해 비슷한지 여부를 확인
are_close = np.isclose(df_prep["Total Volume"], df_prep["Total Volume2"])
df_prep[~are_close][["Total Volume", "Total Volume2"]]

 

df_prep["month"] = df_prep["Date2"].dt.month
df_prep["day"] = df_prep["Date2"].dt.day

 

df_prep["region"].value_counts()

 

# 불필요한 컬럼 삭제
df_drop = df_prep.drop(labels=["Unnamed: 0", "Date", "Date2", "Total Bags", "Total Bags2", "Total Volume2"], axis=1)

 

from sklearn.preprocessing import OneHotEncoder

# 원핫인코딩
encoder = OneHotEncoder(sparse_output=False)
encoded_data = encoder.fit_transform(df_drop[["type", "region"]])

encoded_df = pd.DataFrame(
    encoded_data, columns=encoder.get_feature_names_out(["type", "region"])
)

df_encoded = df_drop.drop(columns=["type", "region"])
df_encoded = pd.concat([df_encoded, encoded_df], axis=1)

 

from sklearn.model_selection import train_test_split

# 데이터 분리
X = df_encoded.drop(labels=["AveragePrice"], axis=1)
y = df_encoded["AveragePrice"]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

 

 

모델 학습 및 평가

from sklearn.tree import DecisionTreeRegressor
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from xgboost import XGBRegressor

lr = LinearRegression()
dtr = DecisionTreeRegressor()
rfr = RandomForestRegressor()
xgbr = XGBRegressor()

 

from sklearn.metrics import mean_squared_error, r2_score

def model_eval(model):
    print(f"===== Model {model} Evaluation =====")
    print(f"Train: {model.score(X_train, y_train)}")
    print(f"Test: {model.score(X_test, y_test)}")

    predictions = model.predict(X_test)
    rmse = np.sqrt(mean_squared_error(y_test, predictions))
    r2 = r2_score(y_test, predictions)

    print(f"RMSE: {rmse}")
    print(f"R2 Score: {r2}")
    print("=" * 50)

 

# 모델 학습
lr.fit(X_train, y_train)
dtr.fit(X_train, y_train)
rfr.fit(X_train, y_train)
xgbr.fit(X_train, y_train)

 

# 모델 평가
models = [lr, dtr, rfr, xgbr]

for model in models:
    model_eval(model)