# https://www.geeksforgeeks.org/dsa/random-forest-classifier-using-scikit-learn/

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris

# Load the Iris dataset from scikit-learn
iris = load_iris()

df = pd.DataFrame(data=iris.data, columns=iris.feature_names)

# Add the target (class labels) as a new column
df['target'] = iris.target

# Separate features (X) and target labels (y)
X = df.iloc[:, :-1].values   # all columns except the last one
y = df.iloc[:, -1].values    # only the last column (target)

# Split data into training set and test set
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Standardize features
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)  # learn scaling on training data
X_test = scaler.transform(X_test)        # apply the same scaling to test data

# Create a Random Forest classifier with 100 trees
classifier = RandomForestClassifier(n_estimators=100, random_state=42)


classifier.fit(X_train, y_train)

# Use the trained model to predict the labels of the test set
y_pred = classifier.predict(X_test)

# Calculate accuracy: percentage of correct predictions
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy * 100:.2f}%')

# Build a confusion matrix to see detailed prediction results
conf_matrix = confusion_matrix(y_test, y_pred)

# Plot the confusion matrix as a heatmap
plt.figure(figsize=(8, 6))
sns.heatmap(
    conf_matrix,
    annot=True,              # show numbers in the cells
    fmt='g',                 # show numbers as integers
    cmap='Blues',            # color map
    cbar=False,              # no color bar
    xticklabels=iris.target_names,  # names on x-axis
    yticklabels=iris.target_names   # names on y-axis
)

plt.title('Confusion Matrix Heatmap')
plt.xlabel('Predicted Labels')
plt.ylabel('True Labels')
plt.show()

# Get feature importance scores from the trained Random Forest
feature_importances = classifier.feature_importances_

# Plot feature importance to see which features matter most
plt.barh(iris.feature_names, feature_importances)
plt.xlabel('Feature Importance')
plt.title('Feature Importance in Random Forest Classifier')
plt.show()