import pandas as pd  
from sklearn.ensemble import RandomForestClassifier  
from sklearn.feature_selection import RFE  
from sklearn.model_selection import cross_val_score  
import matplotlib.pyplot as plt  
import numpy as np  

# Read Excel data  
df = pd.read_excel("C:/Users/fdy12/Desktop/fdy_dataset-0-predict6.xlsx")  # replace with your Excel file path

# Separate features and labels  
X = df.iloc[:, :-1]   # features: all rows, all columns except the last  
y = df.iloc[:, -1]    # labels: all rows, the last column  

# Initialize random forest classifier  
estimator = RandomForestClassifier(n_estimators=100, random_state=42)  

# Initialize RFE instance, we will determine the optimal number of features later using cross-validation  
selector = RFE(estimator, step=1)  

# Prepare lists to store cross-validation scores for different feature counts  
cv_scores = []  
num_features = []  

# Perform cross-validation for different numbers of features  
for n_features in range(1, X.shape[1] + 1):  
    selector.n_features_to_select = n_features  
    X_transformed = selector.fit_transform(X, y)  
    score = cross_val_score(estimator, X_transformed, y, cv=5, scoring='accuracy').mean()  
    cv_scores.append(score)  
    num_features.append(n_features)  

# Find the optimal number of features  
best_num_features = num_features[cv_scores.index(max(cv_scores))]  
print(f"Best number of features: {best_num_features}")  

# Refit RFE using the optimal number of features  
selector.n_features_to_select = best_num_features  
X_transformed = selector.fit_transform(X, y)  

# Get selected feature indices and names  
selected_feature_indices = np.where(selector.support_)[0]  
selected_features = np.array(X.columns)[selected_feature_indices]  

# Fit the random forest model to obtain feature importances  
estimator.fit(X_transformed, y)  
importances = estimator.feature_importances_  

# Plot cross-validation scores vs number of features  
plt.figure(figsize=(10, 5))  
plt.plot(num_features, cv_scores, marker='o')  
plt.title('Cross-Validation Scores by Number of Features')  
plt.xlabel('Number of Features')  
plt.ylabel('Cross-Validation Score')  
plt.axvline(x=best_num_features, color='r', linestyle='--', label=f'Optimal: {best_num_features} features')  
plt.legend()  
plt.show()  

# Plot feature importances of the optimal feature set  
plt.figure(figsize=(10, 5))  
plt.bar(selected_features, importances)  
plt.title('Feature Importances of the Optimal Feature Set')  
plt.xlabel('Features')  
plt.ylabel('Importance')  
plt.xticks(rotation='vertical')  
plt.tight_layout()  
plt.show()  
