import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder

"""
Cross validation consists in doing multiple validations on different training and validation sets.
This way we have better prediction plus we don't have to bother to split the dataset into training and validation set since
it's done by the pipeline.
"""

# 
# Get and prepare data
# 
# Read the data
data = pd.read_csv('../data/data.csv')
# handle missing values
data = data.dropna(subset=['Price'])
# Separate target from predictors
y = data.Price
X = data.drop(['Price'], axis=1)
# Select categorical columns with relatively low cardinality (convenient but arbitrary)
categorical_cols = [cname for cname in X.columns if X[cname].nunique() < 10 and 
                        X[cname].dtype == "object"] # indicate column has text
# Select numerical columns
numerical_cols = [cname for cname in X.columns if X[cname].dtype in ['int64', 'float64']]

# 
# Declare preprocessors
# 
# Preprocessing for numerical data
numerical_transformer = SimpleImputer(strategy='constant')
# Preprocessing for categorical data
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder(handle_unknown='ignore'))
])
# Bundle preprocessing for numerical and categorical data
preprocessor = ColumnTransformer(
    transformers=[
        ('num', numerical_transformer, numerical_cols),
        ('cat', categorical_transformer, categorical_cols)
    ])

# 
# Define the model
# 
from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor(n_estimators=100, random_state=0)

# 
# Create the Pipeline
# 
from sklearn.metrics import mean_absolute_error

# Bundle preprocessing and modeling code in a pipeline
my_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                              ('model', model)
                             ])

# 
# Evaluate the Pipeline using Cross validation
# 
from sklearn.model_selection import cross_val_score

# Multiply by -1 since sklearn calculates *negative* MAE
scores = -1 * cross_val_score(my_pipeline, X, y,
                              cv=5, # specify the number of folds
                              scoring='neg_mean_absolute_error')

print("MAE scores:", scores)
print("Average MAE score (across experiments):", scores.mean())