<jupyter_start><jupyter_text>DataCamp Certification Case Study Project BriefYou have been hired as a data scientist at Discount Motors, a used car dealership in the UK. The dealership is expanding and has hired a large number of junior salespeople. Although promising, these junior employees have difficulties pricing used cars that arrive at the dealership. Sales have declined 18% in recent months, and management would like your help designing a tool to assist these junior employees.To start with, they would like you to work with the Toyota specialist to test your idea(s). They have collected some data from other retailers on the price that a range of Toyota cars were listed at. It is known that cars that are more than £1500 above the estimated price will not sell. The sales team wants to know whether you can make predictions within this range.You will need to present your findings in two formats:- You must submit a written report summarising your analysis to your manager. As a data science manager, your manager has a strong technical background and wants to understand what you have done and why. - You will then need to share your findings with the head of sales in a 10 minute presentation. The head of sales has no data science background but is familiar with basic data related terminology. The data you will use for this analysis can be accessed here: `"data/toyota.csv"`  Table of Contents 1. **[Dataset](Dataset)**2. **[Analysis Plan](Analysis)**3. **[Exploratory Data Analysis](Exploratory)**4. **[Feature Engineering](Feature)**5. **[Machine Learning Model](Machine)**  1. Dataset  The Toyota specialist provided a dataset containing historical sales data of Toyota cars from retailers, which consists of a total of **6738 rows** and **9 columns**. All the variables in this dataset are listed and described as below, where `price` will be our target variable.  1.1 Variables| Variables | Details                                                                                                       ||--------------|---------------------------------------------------------------------------------------------------------------|| model        | Character, the model of the car, 18 possible values                                                           || year         | Numeric, year of manufacture from 1998 to 2020                                                                || **price**        | Numeric, listed value of the car in GBP                                                                       || transmission | Character, one of "Manual", "Automatic", "Semi-Auto" or "Other"                                               || mileage      | Numeric, listed mileage of the car at time of sale                                                             || fuelType     | Character, one of "Petrol", "Hybrid", "Diesel" or "Other"                                                     || tax          | Numeric, road tax in GBP. Calculated based on CO2 emissions or a fixed price depending on the age of the car. || mpg          | Numeric, miles per gallon as reported by manufacturer                                                         || engineSize   | Numeric, listed engine size, one of 16 possible values                                                        |<jupyter_code>import pandas as pd
import numpy as np
import scipy.stats as st
df = pd.read_csv('data/toyota.csv')
df.head()
df.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
RangeIndex: 6738 entries, 0 to 6737
Data columns (total 9 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   model         6738 non-null   object 
 1   year          6738 non-null   int64  
 2   price         6738 non-null   int64  
 3   transmission  6738 non-null   object 
 4   mileage       6738 non-null   int64  
 5   fuelType      6738 non-null   object 
 6   tax           6738 non-null   int64  
 7   mpg           6738 non-null   float64
 8   engineSize    6738 non-null   float64
dtypes: float64(2), int64(4), object(3)
memory usage: 473.9+ KB<jupyter_text>1.2 Handling missing values<jupyter_code>df.isna().sum()
for col in df.columns:
    if df[col].dtype.name == 'object':
        if np.nan in df[col].unique():
            print('nan detected in', str(col))
        else:
            print('no nan detected in', str(col))<jupyter_output>no nan detected in model
no nan detected in transmission
no nan detected in fuelType<jupyter_text>After checking for missing values in every single column, it seems that the dataset has **no missing values** at all, so no action needs to be taken.  1.3 Handling duplicates<jupyter_code>df.duplicated().sum()
df = df.drop_duplicates()
df.duplicated().sum()<jupyter_output><empty_output><jupyter_text>There were **39 duplicate rows** found, which were immediately **dropped** as they would create bias in our insights and model later on.  1.4 Handling characters<jupyter_code>columns_cat = ['model', 'transmission', 'fuelType']
for col in columns_cat:
    df[col] = df[col].str.strip()
    print(df[col].unique())<jupyter_output>['GT86' 'Corolla' 'RAV4' 'Yaris' 'Auris' 'Aygo' 'C-HR' 'Prius' 'Avensis'
 'Verso' 'Hilux' 'PROACE VERSO' 'Land Cruiser' 'Supra' 'Camry' 'Verso-S'
 'IQ' 'Urban Cruiser']
['Manual' 'Automatic' 'Semi-Auto' 'Other']
['Petrol' 'Other' 'Hybrid' 'Diesel']<jupyter_text>Extra spaces in the beginning and at the end of each non numerical value were removed to achieve **cleaner data**. The columns with numerical data types should be left as is, as the numerical data type already restricts any character error in the data.  1.5 Handling data types<jupyter_code>columns_cat = ['model', 'transmission', 'fuelType']
for col in columns_cat:
    df[col] = df[col].astype('category')
df['year'] = df['year'].astype('category')

columns_cat = [col for col in df.columns if df[col].dtype.name == 'category']
for col in columns_cat:
    print(df[col].cat.categories)
df.dtypes<jupyter_output><empty_output><jupyter_text>The column `year` was converted into the **category data type** along with the other columns that previously had the object data type, namely `model`, `transmission`, and `fuelType`. Compared to the object data type, the category data type is much **smaller in size**, which is more efficient for Pandas to process.  2. Analysis Plan This project is about predicting the prices of used cars that have already been sold, where the prices exist in the Toyota dataset that we have. This calls for a **supervised machine learning**. Since the target variable, namely `price`, is **numeric**, the model of choice will be **regression**. As for the model, a **multivariate linear regression** will be used to try and explain the data. If the linear regression model is able to achieve a decent result with initial test, then the decision will be to proceed with the linear regression  as the model of choice. Since this is a regression problem, the model evaluation will be based on the different metrics for regression to assess entire performance of the model.Before we are able to predict the prices of the used cars, we need to get a better understanding of the sales trends in our dataset and discover which variables correlate with the price of the cars. With that said, the plan of analysis to execute our approach is as follows:- Exploratory Data Analysis (EDA) to discover trends in sales of the used cars and highlight the variables that affect sales and price- Feature Engineering and Selection based on the results of the EDA performed- Testing the regression model and making improvements based on the model evaluations to achieve better scores and/or prediction efficiency  3. Exploratory Data Analysis<jupyter_code>import matplotlib.pyplot as plt
import seaborn as sns

sns.set_theme(style='darkgrid', font_scale=1.25, context='notebook', palette='bright')
def labels(title, x, y):
    plt.title(title)
    plt.xlabel(x)
    plt.ylabel(y)<jupyter_output><empty_output><jupyter_text>3.1 Overall Price Distribution<jupyter_code>plt.figure(figsize=(16,4))
plt.suptitle('Price Distribution', fontsize=20, y=1.05)

plt.subplot(1,3,1)
sns.histplot(data=df, x='price', stat='frequency', bins=50, kde=True)
labels('Histogram', 'Frequency', 'Price')

plt.subplot(1,3,2)
sns.boxplot(data=df, x='price', width=0.5)
labels('Boxplot', '', 'Price')

plt.subplot(1,3,3)
sns.ecdfplot(data=df, x='price')
labels('ECDF', 'Proportion', 'Price')

plt.show()
df['price'].describe()
iqr = st.iqr(df['price'])
q3 = np.percentile(df['price'], 75)
maximum=q3+iqr
maximum, q3, iqr<jupyter_output><empty_output><jupyter_text>**Conclusions**- The distribution of used cars sales price is normally distributed, with a mean of £12529 and a median of £10798.- The distribution is right-skewed, explained by having a mode less than the median and a median less than the mean.- Being right-skewed indicates that the outliers are to the right, where the higher prices are.- Cheaper cars are sold more than more expensive cars.- The maximum of the box plot is at £21723, so the prices above that are considered outliers.- Around 75% of the prices are below £15000  3.2 Categorical Variables To explain the categorical variables, tables, bar charts, count plots, and histograms will be used. Tables will best explain columns with numerous categories, while columns with less catogeries can be best explained with histograms  3.2.1 Year<jupyter_code>df = df.loc[df['year']!=1998]
df
year_df = df.groupby('year').agg({'year':'count', 'price':['mean','median']}).sort_values(('year','count'), ascending=False)
year_df
year_df.sort_values(('price','mean'), ascending=False)
plt.figure(figsize=(16,4))
plt.suptitle('Distributed by Year', fontsize=20, y=1.05)

plt.subplot(1,2,1)
sns.countplot(data=df, x='year', palette="Spectral")
plt.xticks(rotation=90)
labels('Count per Year', 'Year', 'Count')

plt.subplot(1,2,2)
sns.barplot(data=df, x='year', y='price', palette="Spectral")
plt.xticks(rotation=90)
labels('Average Price per Year', 'Year', 'Price')
            
plt.show()<jupyter_output><empty_output><jupyter_text>**Conclusions**- Newer cars are typically more expensive than older cars, except for one car manufactured in 1998 that was overpriced, which is considered as an outlier and was dropped.- Most of the cars sold were manufactured in 2017, forming left-skewed normal distribution, with 2017 as the mode.- As it is left-skewed, the outliers in this case are older cars, and newer cars are more likely to be sold than older cars.  3.2.2 Model<jupyter_code>model_df = df.groupby('model').agg({'model':'count', 'price':['mean','median']}).sort_values(('model','count'), ascending=False)
model_df
model_df.sort_values(('price','mean'), ascending=False)
plt.figure(figsize=(16,4))
plt.suptitle('Distributed by Model', fontsize=20, y=1.05)

plt.subplot(1,2,1)
sns.countplot(data=df, x='model', order=df['model'].value_counts().index, palette="Spectral")
plt.xticks(rotation=90)
labels('Count per Model', 'Model', 'Count')

plt.subplot(1,2,2)
sns.barplot(data=df, x='model', y='price', order=df['model'].value_counts().index, palette="Spectral")
plt.xticks(rotation=90)
labels('Average Price per Model', 'Model', 'Price')
            
plt.show()<jupyter_output><empty_output><jupyter_text>**Conclusions**- Yaris and Aygo are the best selling cars, with Auris, C-HR, and RAV4 trailing behind quite far in that particular order.- Supra is the most expensive car sold, however, it is not doing well in terms of the quantity of sales.- There are less sales for expensive cars. However, even though IQ, Urban Cruiser, and Verso-S are cheap, they are not doing well in terms of sales.  3.2.3 Transmission<jupyter_code>transmission_df = df.groupby('transmission').agg({'transmission':'count', 'price':['mean','median']}).sort_values(('transmission','count'), ascending=False)
transmission_df
transmission_df.sort_values(('price','mean'), ascending=False)
df['transmission'].value_counts()
plt.figure(figsize=(16,4))
plt.suptitle('Grouped by Transmission', fontsize=20, y=1.05)
plt.subplot(1,2,1)
sns.countplot(data=df, x='transmission', order=df['transmission'].value_counts().index)
labels('Count per Transmission', 'Transmission', 'Count')
plt.subplot(1,2,2)
sns.barplot(data=df, x='transmission', y='price', order=df['transmission'].value_counts().index)
labels('Average Price per Transmission', 'Transmission', 'Price')
plt.show()
plt.figure(figsize=(16,8))
plt.suptitle('Price Distribution based on Transmission', fontsize=20, y=0.98)
sns.histplot(data=df, x='price', hue='transmission', hue_order=[x for x in transmission_df.index], element='step')
labels('', 'Price', 'Count')
plt.show()<jupyter_output><empty_output><jupyter_text>**Conclusions**- Manual cars have the most sales, with automatic cars trailing behind.- In terms of price, automatic cars are the most expensive, with semi-auto trailing behind, and then other cars and manual in that order.- The manual cars prices form a right-skewed normal distribution, meaning that cheaper manual cars are more likely to be sold than more expensive ones.  3.2.4 Fuel Type<jupyter_code>fuel_df = df.groupby('fuelType').agg({'fuelType':'count', 'price':['mean','median']}).sort_values(('fuelType','count'), ascending=False)
fuel_df
fuel_df.sort_values(('price','mean'), ascending=False)
plt.figure(figsize=(16,4))
plt.suptitle('Grouped by Fuel Type', fontsize=20, y=1.05)
plt.subplot(1,2,1)
sns.countplot(data=df, x='fuelType', order=df['fuelType'].value_counts().index)
labels('Count per Fuel Type', 'Fuel Type', 'Count')
plt.subplot(1,2,2)
sns.barplot(data=df, x='fuelType', y='price', order=df['fuelType'].value_counts().index)
labels('Average Price per Fuel Type', 'Fuel Type', 'Price')
plt.show()
plt.figure(figsize=(16,8))
plt.suptitle('Price Distribution based on Fuel Type', fontsize=20, y=0.98)
sns.histplot(data=df, x='price', hue='fuelType', hue_order=[x for x in fuel_df.index], element='step')
labels('', 'Price', 'Count')
plt.show()<jupyter_output><empty_output><jupyter_text>**Conclusion**- Most of the cars that were sold used Petrol. Hybrid comes next, trailing by quite far, and then Diesel.- Hybrid cars are the most expensive, while Petrol cars are the cheapest.- The prices of the petrol cars form a right-skewed normal distribution, which means that there are more cheaper petrol cars are sold than expensive ones.  3.3 Numerical Variables<jupyter_code>plt.figure(figsize=(16,8))
g = sns.pairplot(df, kind='kde', diag_kind='kde', corner=True, aspect=1.15)
g.map_lower(sns.regplot, scatter=False)
plt.show()<jupyter_output><empty_output><jupyter_text>**Conclusions**Using multiple KDE plots and regression plots, we can make inferences for our numerical variables, as the following:- Out of all the variables, we can see that the best fitting line for price against engine size shows that these two variables are very much positively correlated.- Price is positively correlated with tax, though not as much as engine size. Same with engine size, the higher the tax, the higher the price of the car.- Price and miles per gallon are independent of each other, which indicates that there is a great chance mpg will not help predict the car prices.- Price and mileage are negatively correlated, which means that a high mileage decreases the price of the car.  3.4 Multivariate Analysis This section of analysis attempts to combine two separate variables in order to make inferences about the car prices.  3.4.1 Model and Transmission<jupyter_code>df.groupby(['model', 'transmission']).agg({'model':'count', 'price':['mean','median']}).sort_values(('model','count'), ascending=False).dropna().head(20)<jupyter_output><empty_output><jupyter_text>3.4.2 Model and Fuel Type<jupyter_code>df.groupby(['model', 'fuelType']).agg({'model':'count', 'price':['mean','median']}).sort_values(('model','count'), ascending=False).dropna().head(20)<jupyter_output><empty_output><jupyter_text>3.4.3 Transmission and Fuel Type<jupyter_code>df.groupby(['transmission', 'fuelType'], dropna=True).agg({'transmission':'count', 'price':['mean','median']}).sort_values(('transmission','count'), ascending=False).dropna()<jupyter_output><empty_output><jupyter_text>3.4.4 Year and Model<jupyter_code>df.groupby(['year', 'model'], dropna=True).agg({'year':'count', 'price':['mean','median']}).sort_values(('year','count'), ascending=False).dropna().head(20)<jupyter_output><empty_output><jupyter_text>**Conclusions**- Grouping by the model and transmission, we can see that Manual Aygo is the most popular type of car sold, with just costing just around £7686. Manual Yaris comes in second and is selling more than its Automatic counterpart and cost around respectively £9804 and £11890.- Grouping by model and fuel type, the top two most sold are Petrol Aygo and Yaris Petrol- Grouped by the transmission and fuel type, we see that Manual Petrol and Automatic Hybrid make the most sales.- Grouped by year of manufacture and model, Aygo 2017 has the most sales, and then Yaris 2017 and 2019.  4. Feature Engineering  Based on our EDA, there are multiple variables that are of interest to include in our machine learning model. Firstly, in our numerical variables, it was seen that mileage, tax, and especially engine size were positively correlated to the price of the car. By their normally distributed data, we also saw that cars manufactured in certain years, cars with certain model types, using certain types of transmission and fuel had a correlation to the sales count and prices of cars.To further analyze which types of cars will be able to help in our price prediction, the categorical features will be broken further down for the machine learning model to test. As for the numerical features, since they all have different magnitudes, we will have to standardize them in order to eliminate the bias that can derive from the difference in magnitudes. Before we proceed in the model building, we need to make sure that our data is a single scalar number so that the machine learning will be able to read the data and develop its predictive ability.  4.1 Encoding Categorical features are divided ordinal and nominal data type. This is important because ordinal and nominal data types are treated differently in the encoding process. The ordinal features will use the Label Encoding method to make sure that they are ordered correctly, while the nominal features will go through One Hot Encoding using Pandas get_dummies function to have each category in the column a separate feature on their own. In our dataset, year is considered to be ordinal, while the rest of categorical features are nomimal.<jupyter_code>data = df
from sklearn.preprocessing import LabelEncoder
label = LabelEncoder()
labeled = label.fit_transform(data['year'])
data['year'] = labeled
data['year'].value_counts()
cats = ['model','transmission','fuelType']
encoded = pd.get_dummies(data[cats], prefix=cats)
data = data.join(encoded)
data.head()
for col in data.columns:
    if data[col].dtype.name == 'category':
        data = data.drop(col, axis=1)
data.columns<jupyter_output><empty_output><jupyter_text>The pre-existing categorical columns that are were one-hot-encoded are dropped, since our dataset now has separate columns for each separate categories in those columns.  4.2 Splitting Test and Training Data Before we get to scaling the numerical values, one step we need to do before that is splitting the data into test set and training set. The reason we do not scale before is to prevent bias in the scaling. In the real world, the test set is data that our prediction model has never seen before, and thus we treat it the same way in the model building process.<jupyter_code>from sklearn.model_selection import train_test_split
train, test = train_test_split(data, train_size = 0.75, test_size = 0.25, random_state = 13)<jupyter_output><empty_output><jupyter_text>4.3 Scaling To eliminate bias caused by difference in the numerical magnitudes, the values of each numerical columns are scaled using the Standard Scaler method. The Standard Scaler is a method that by default standardizes numerical features by subtracting the data by the mean and dividing it by the standard deviation. Depending on the variability of each data point, the data point will be either be a negative or positive number around 0. Make sure that this is done for both the training and the testing set, albeit separately.<jupyter_code>from sklearn.preprocessing import StandardScaler
columns_num = [col for col in df.columns if df[col].dtype.name != 'category']
columns_num
scaler_test = StandardScaler()
scaler_train = StandardScaler()
columns_num = [col for col in df.columns if df[col].dtype.name != 'category']

scaler_train.fit(train[columns_num])
train[columns_num] = scaler_train.transform(train[columns_num])

scaler_test.fit(test[columns_num])
test[columns_num] = scaler_test.transform(test[columns_num])

train.head()
plt.figure(figsize=(16,12))
sns.set_theme(style='ticks', font_scale=0.9, context='notebook', palette='bright')
plt.suptitle('Feature Correlation', fontsize=20, y=0.98)

corr = train.corr()
mask = np.triu(np.ones_like(corr, dtype=bool))
cmap = sns.diverging_palette(220, 20, as_cmap=True)
sns.heatmap(corr, annot=False, linewidths=1.5, cmap=cmap, vmin=-1, vmax=1, mask=mask)<jupyter_output><empty_output><jupyter_text>The above correlation graph shows how each feature interact with another. The color map used in this graph signal red for positive correlation, blue for negative correlation, and pure white for no correlation at all. Mostly, we are interested in seeing how the variables we have just created interacts with our target variable price.- Dependent variables that are clear to have negative correlation to price are `Petrol Fuel type`, `annual transmission`, `Yaris model`, `Aygo model`, and `mileage`.- Dependent variables that are clear to have positive correlation to price are `Hibrid Fuel type`, `Automatic transmission`, `Supra model`, `Land Cruiser model`, `Corolla model`, `C-HR model`, `engine size`, and `tax`. (Note that there are other positive correlations between price and other dependent variables, but closer to 0.)  4.4 Splitting Feature and Target Variables Previously, our dataset was already split into training and testing set. They are further divided into feature variables and target variable, where our target variable is the price of the car.<jupyter_code>y_train = train['price']
X_train = train.drop('price', axis=1)
y_test = test['price']
X_test = test.drop('price', axis=1)
X_test.shape, X_train.shape, y_test.shape, y_train.shape<jupyter_output><empty_output><jupyter_text>5. Machine Learning Model  The goal of this section is to build a model that is able to predict the price of the cars using the feature variables as input.As previously mentioned in the analysis plan, as our first machine learning model, we will use the simplest model, which is the linear regression model. If the model performs to a decent level based on its evaluation scores, we will proceed to use the model and attempt to improve the predictive ability of the model.  5.1 Initial Model Test The initial model test uses all the features that exist in our dataset. To evaluate our initial model, we will use the Root Mean Squared Error (RMSE), which is the standard deviation of the residuals (prediction errors) given in absolute terms. The lower the RMSE score, the lower our prediction errors, in other words, the better our prediction results. Based on a rule of thumb, a good RMSE ranges around 0.2 and 0.5, which indicates that the model has a relatively accurate predictive ability. Amazingly, the linear regression model was able to achieve around 0.27 score of RMSE, which is considered to be decent based on the rule of thumb. The evalation is done using cross validation, switching the folds in the training data to ensure that the model is robust when tested with different data.<jupyter_code>from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
reg = LinearRegression()
reg.fit(X_train,y_train)
cv_results = cross_val_score(reg, X_train, y_train, scoring='neg_root_mean_squared_error', cv=5)
print(abs(cv_results))
print(abs(np.mean(cv_results)))<jupyter_output>[0.24063041 0.29676593 0.30261413 0.25894769 0.25946638]
0.2716849082895122<jupyter_text>5.2 Reducing Dimensionality While the model has already achieved a good evaluation score, the model is still using practically all the features that exist in the dataset. That means there is more calculation done when predicting the target variable, and the prediction is inefficient. As such, we need to reduce the dimension of the data used in the model by removing columns that only have a small impact on the model's predictive ability. We use the Cross Validated Recursive Feature Elimination to help eliminate the features that do not positively impact the model's prediction based on the scores outputted.<jupyter_code>from sklearn.feature_selection import RFECV
from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_error
min_features_to_select=1
rfecv = RFECV(estimator=reg, step=1, cv=KFold(5), scoring='neg_root_mean_squared_error', min_features_to_select=min_features_to_select)
rfecv.fit(X_train,y_train)
print("Optimal number of features : %d" % rfecv.n_features_)
print(rfecv.score(X_train,y_train))
print(abs(rfecv.grid_scores_))
sns.set_theme(style='darkgrid', font_scale=1.25, context='notebook', palette='bright')

plt.figure(figsize=(6,4))
plt.suptitle('RMSE for Features Used', fontsize=20, y=1.05)
plt.plot(range(min_features_to_select, len(rfecv.grid_scores_)+min_features_to_select), abs(rfecv.grid_scores_))
labels('', 'Number of Features Used', 'RMSE score')
plt.ylim([0,1])
plt.show()
features = pd.DataFrame(X_train.columns)
features['ranking'] = rfecv.ranking_
features['support'] = rfecv.support_.astype('bool')
features[features['support'] == False]
X_train_new = X_train[X_train.columns[rfecv.support_]]
X_train_new.shape
X_test_new = X_test[X_train.columns[rfecv.support_]]
X_test_new.shape
reg = LinearRegression()
reg.fit(X_train_new,y_train)
cv_results = cross_val_score(reg, X_train_new, y_train, scoring='neg_root_mean_squared_error', cv=5)
print(abs(cv_results))
print(abs(np.mean(cv_results)))<jupyter_output>[0.24063041 0.29676593 0.30256862 0.25894769 0.25921224]
0.2716249762783113<jupyter_text>Initially, after the feature engineering section, we had used 31 columns in total. With the reduced dimension, we now have 29 columns, with 2 columns reduced which are `model_GT86` and `transmission_Automatic`. Even then, the model is still able to achieve a great RMSE score. In the graph above where we visualized the number of features used and the RMSE scores achieved, we can see that even with just 20 variables, the model should still be able to achieve a RMSE score below 0.3, where a 0.4 RMSE square is already considered acceptable.  5.3 Final Evaluation We have already determined that our model has good predictive ability based on its RMSE score on cross validation. For our final evaluation, we will finally use the model to explain the testing set. The result of the evaluation seen below show that the model also has a low Mean Absolute Error, a low Mean Squared Error, and a R-Squared close to 1, that altogether signal to a good prediction result done by our linear regression model.<jupyter_code>from sklearn import metrics
def print_evaluate(true, pred):
    mae = metrics.mean_absolute_error(true, pred)
    mse = metrics.mean_squared_error(true, pred)
    rmse = np.sqrt(metrics.mean_squared_error(true, pred))
    r2 = metrics.r2_score(true, pred)
    print("Mean Absolute Error : %f" % mae)
    print("Mean Squared Error : %f" % mse)
    print("Root Mean Absolute Error : %f" % rmse)
    print("R-Squared : %f" % r2)
#     return mae, mse, rmse, r2
y_pred = reg.predict(X_test_new)
print_evaluate(y_test,y_pred)<jupyter_output>Mean Absolute Error : 0.175891
Mean Squared Error : 0.076460
Root Mean Absolute Error : 0.276514
R-Squared : 0.923540<jupyter_text>When plotting the predicted value and the actual value of prices, we also see a good line of best fit indicated by a positive correlation.<jupyter_code>plt.figure(figsize=(6,6))
plt.suptitle('Prediction vs Actual', fontsize=20, y=0.98)
sns.regplot(y_test, y_pred, marker='.')
labels('', 'Actual', 'Predicted')
plt.show()
print(reg.intercept_)
print(reg.coef_)<jupyter_output>0.9587296154960188
[ 0.26515402 -0.1794052  -0.04653299 -0.0248698   0.21154051 -0.90857169
 -0.72042164 -1.31726286 -0.05104919  0.16412538 -0.12048411  0.38382818
 -0.96848582  2.59386031  1.31612938 -0.14066261 -0.19060085  3.8240754
 -0.95656993 -0.73813586 -0.9888152  -1.1514441  -0.19036505  0.1438742
  0.01238209 -0.29152055  0.18874831  0.15500333 -0.05223109]<jupyter_text>The formula of our final linear regression model is written as below.<jupyter_code>print('y_hat = ', end='')
for i, x in enumerate(X_train_new.columns):
    print('('+str(rfecv.estimator_.coef_[i])+'*'+str(x)+') + ', end='')
print(rfecv.estimator_.intercept_)<jupyter_output>y_hat = (0.2651540172815917*year) + (-0.17940520338908858*mileage) + (-0.04653299193680081*tax) + (-0.024869799803269473*mpg) + (0.2115405101638497*engineSize) + (-0.9085716921678193*model_Auris) + (-0.7204216400041149*model_Avensis) + (-1.3172628646219469*model_Aygo) + (-0.05104918980564464*model_C-HR) + (0.16412538087009887*model_Camry) + (-0.12048411457882514*model_Corolla) + (0.3838281796465239*model_Hilux) + (-0.9684858194770936*model_IQ) + (2.5938603052933216*model_Land Cruiser) + (1.3161293791307533*model_PROACE VERSO) + (-0.1406626076736192*model_Prius) + (-0.19060085478617866*model_RAV4) + (3.8240753998909263*model_Supra) + (-0.9565699302781712*model_Urban Cruiser) + (-0.7381358644751473*model_Verso) + (-0.9888152038499867*model_Verso-S) + (-1.151444095729958*model_Yaris) + (-0.19036505346684146*transmission_Manual) + (0.14387419559406533*transmission_Other) + (0.012382091376479845*transmission_Semi-Auto) + (-0.2915205469849883*fuelType_Diesel) + (0.1887483079555975*fuelType_H[...]
{'fraction_non_alphanumeric': 0.10375919909832261, 'fraction_numerical': 0.04432142146787774, 'mean_word_length': 4.781333844384822, 'pattern_counts': {'":': 0, '<': 94, '<?xml version=': 0, '>': 94, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 21, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '25', 'dir': 'jupyter-structured-clean-dedup', 'id': '654509', 'license': 'CC-BY-3.0', 'n_tokens_mistral': 9703, 'n_tokens_neox': 8659, 'n_words': 3379, 'path': 'Regression/Car Price Prediction/.ipynb_checkpoints/Fakhri Nurrahmadi - Car Prices Prediction-checkpoint.ipynb', 'repo_name': 'fnurrahmadi/fnurrahmadi', 'size': '30166'}