Spaces:
Sleeping
Sleeping
Delete app.py
Browse files
app.py
DELETED
|
@@ -1,250 +0,0 @@
|
|
| 1 |
-
# start by importing the necessary packages
|
| 2 |
-
#standard
|
| 3 |
-
import numpy as np
|
| 4 |
-
import pandas as pd
|
| 5 |
-
|
| 6 |
-
#plt packages
|
| 7 |
-
import seaborn as sns
|
| 8 |
-
import altair as alt
|
| 9 |
-
import matplotlib.pyplot as plt
|
| 10 |
-
#streamlit
|
| 11 |
-
import streamlit as st
|
| 12 |
-
|
| 13 |
-
#sklearn
|
| 14 |
-
from sklearn.decomposition import PCA
|
| 15 |
-
from sklearn.preprocessing import StandardScaler
|
| 16 |
-
from sklearn.cluster import KMeans
|
| 17 |
-
from sklearn.metrics import silhouette_score
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
st.set_page_config(page_title="StressedOUT – Cached/DB", page_icon=":skull:", layout="wide")
|
| 22 |
-
st.title("StressedOOUT – Looking into a dataset of stressed students (Cached)")
|
| 23 |
-
st.caption("Reads .csv files. Uses Streamlit caching and a form submit gate.")
|
| 24 |
-
|
| 25 |
-
BASE_DIR = "StressLevelDataset.csv" #
|
| 26 |
-
|
| 27 |
-
@st.cache_data
|
| 28 |
-
def load_data(path):
|
| 29 |
-
data = pd.read_csv(path)
|
| 30 |
-
return data
|
| 31 |
-
|
| 32 |
-
data = load_data(BASE_DIR).drop(columns=['future_career_concerns', 'anxiety_level', 'depression', 'bullying','peer_pressure'])
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
with st.sidebar:
|
| 36 |
-
st.header("Filters")
|
| 37 |
-
with st.form("filters"):
|
| 38 |
-
analysis = st.radio(
|
| 39 |
-
"Select your dataset",
|
| 40 |
-
('PCA reduced', 'No dimensionality reduction'),
|
| 41 |
-
captions=('PCA reduced', 'No dimensionality reduction')
|
| 42 |
-
)
|
| 43 |
-
k = st.slider("Select number of clusters (k)", 2, 10, 4, step=1)
|
| 44 |
-
iterations = st.slider("Select number of iterations to show", 1, 10, 5, step=1)
|
| 45 |
-
seed = st.number_input("Random seed", min_value=0, max_value=100, value=42, step=1)
|
| 46 |
-
st.write("For no dimensionality reduction, the first two features will be used for visualization.")
|
| 47 |
-
feature_x = st.selectbox("Select X-axis feature", data.columns, index=0)
|
| 48 |
-
feature_y = st.selectbox("Select Y-axis feature", data.columns, index=1)
|
| 49 |
-
|
| 50 |
-
submitted = st.form_submit_button("Apply")
|
| 51 |
-
if not submitted:
|
| 52 |
-
st.info("Adjust filters and click **Apply**.")
|
| 53 |
-
st.stop()
|
| 54 |
-
|
| 55 |
-
def kmeans_iteration_demo(X, k, max_iters=iterations):
|
| 56 |
-
# Initialize centers randomly
|
| 57 |
-
np.random.seed(seed)
|
| 58 |
-
centers = X[np.random.choice(len(X), k, replace=False)]
|
| 59 |
-
|
| 60 |
-
fig, axes = plt.subplots(1, max_iters + 1, figsize=(20, 4))
|
| 61 |
-
|
| 62 |
-
for iteration in range(max_iters + 1):
|
| 63 |
-
if iteration == 0:
|
| 64 |
-
# Show initial random centers
|
| 65 |
-
axes[iteration].scatter(X[:, 0], X[:, 1], c='lightgray', alpha=0.6, s=30)
|
| 66 |
-
axes[iteration].scatter(centers[:, 0], centers[:, 1], c='red', s=200, marker='X',
|
| 67 |
-
edgecolors='black', linewidths=2)
|
| 68 |
-
axes[iteration].set_title(f'Iteration {iteration}\n(Random Initialization)')
|
| 69 |
-
|
| 70 |
-
else:
|
| 71 |
-
# Assign points to nearest center
|
| 72 |
-
distances = np.sqrt(((X - centers[:, np.newaxis])**2).sum(axis=2))
|
| 73 |
-
labels = np.argmin(distances, axis=0)
|
| 74 |
-
|
| 75 |
-
# Plot current clustering
|
| 76 |
-
colors = ['blue', 'green', 'red', 'purple', 'orange']
|
| 77 |
-
for j in range(k):
|
| 78 |
-
mask = labels == j
|
| 79 |
-
axes[iteration].scatter(X[mask, 0], X[mask, 1],
|
| 80 |
-
c=colors[j], alpha=0.6, s=30, label=f'Cluster {j+1}')
|
| 81 |
-
|
| 82 |
-
axes[iteration].scatter(centers[:, 0], centers[:, 1], c='black', s=200, marker='X',
|
| 83 |
-
edgecolors='white', linewidths=2)
|
| 84 |
-
axes[iteration].set_title(f'Iteration {iteration}')
|
| 85 |
-
|
| 86 |
-
# Update centers
|
| 87 |
-
new_centers = np.array([X[labels == j].mean(axis=0) for j in range(k)])
|
| 88 |
-
|
| 89 |
-
# Show center movement with arrows
|
| 90 |
-
if iteration > 1:
|
| 91 |
-
for j in range(k):
|
| 92 |
-
axes[iteration].annotate('', xy=new_centers[j], xytext=centers[j],
|
| 93 |
-
arrowprops=dict(arrowstyle='->', lw=2, color='red', alpha=0.7))
|
| 94 |
-
|
| 95 |
-
centers = new_centers
|
| 96 |
-
|
| 97 |
-
axes[iteration].set_xlabel('PC1')
|
| 98 |
-
axes[iteration].set_ylabel('PC2')
|
| 99 |
-
axes[iteration].grid(True, alpha=0.3)
|
| 100 |
-
|
| 101 |
-
plt.tight_layout()
|
| 102 |
-
st.pyplot(fig)
|
| 103 |
-
|
| 104 |
-
if analysis == 'PCA reduced':
|
| 105 |
-
data_scaled = StandardScaler().fit_transform(data)
|
| 106 |
-
data_reduced_df = pd.DataFrame(data_scaled, columns=data.columns)
|
| 107 |
-
st.write('You selected PCA reduced')
|
| 108 |
-
pca = PCA()
|
| 109 |
-
pca_data = pca.fit_transform(data_reduced_df)
|
| 110 |
-
pca_data_pd = pd.DataFrame(pca_data, columns=[f'PC{i+1}' for i in range(pca_data.shape[1])])
|
| 111 |
-
st.write('The PCA reduced data is shown below')
|
| 112 |
-
st.dataframe(pca_data_pd.head(10))
|
| 113 |
-
|
| 114 |
-
explained_variance = pca.explained_variance_ratio_
|
| 115 |
-
cumulative_variance = np.cumsum(explained_variance)
|
| 116 |
-
|
| 117 |
-
st.write("Explained Variance by Component:")
|
| 118 |
-
for i in range(min(10, len(explained_variance))):
|
| 119 |
-
st.write(f"PC{i+1}: {explained_variance[i]:.3f} ({explained_variance[i]*100:.1f}%)")
|
| 120 |
-
|
| 121 |
-
st.write(f"\nFirst 3 components explain {cumulative_variance[2]*100:.1f}% of total variance")
|
| 122 |
-
st.write(f"First 5 components explain {cumulative_variance[4]*100:.1f}% of total variance")
|
| 123 |
-
|
| 124 |
-
#visualizations
|
| 125 |
-
fig,(ax1,ax2)=plt.subplots(1,2,figsize=(12,5))
|
| 126 |
-
|
| 127 |
-
#scree plot
|
| 128 |
-
ax1.plot(range(1,len(explained_variance)+1),explained_variance,marker='o',linestyle='--')
|
| 129 |
-
ax1.set_title('Scree Plot')
|
| 130 |
-
ax1.set_xlabel('Principal Component')
|
| 131 |
-
ax1.set_ylabel('Variance Explained')
|
| 132 |
-
ax1.axvline(x=3,color='r',linestyle='--',label='3 components')
|
| 133 |
-
ax1.axvline(x=5,color='g',linestyle='--',label='5 components')
|
| 134 |
-
ax1.legend()
|
| 135 |
-
ax1.grid()
|
| 136 |
-
#cumulative variance plot
|
| 137 |
-
ax2.plot(range(1,len(cumulative_variance)+1),cumulative_variance,marker='o',linestyle='--',color='orange')
|
| 138 |
-
ax2.set_title('Cumulative Variance Explained')
|
| 139 |
-
ax2.set_xlabel('Number of Principal Components')
|
| 140 |
-
ax2.set_ylabel('Cumulative Variance Explained')
|
| 141 |
-
ax2.axhline(y=0.9,color='r',linestyle='--',label='90% variance')
|
| 142 |
-
ax2.axhline(y=0.95,color='g',linestyle='--',label='95% variance')
|
| 143 |
-
ax2.legend()
|
| 144 |
-
ax2.grid()
|
| 145 |
-
st.pyplot(fig)
|
| 146 |
-
|
| 147 |
-
components_df = pd.DataFrame(
|
| 148 |
-
pca.components_[:5].T, # First 5 components
|
| 149 |
-
columns=[f'PC{i+1}' for i in range(5)],
|
| 150 |
-
index=data_reduced_df.columns
|
| 151 |
-
)
|
| 152 |
-
st.write("PCA Component Loadings (first 5 components):")
|
| 153 |
-
st.dataframe(components_df)
|
| 154 |
-
|
| 155 |
-
# Visualize component loadings for interpretation
|
| 156 |
-
fig, axes = plt.subplots(3, 2, figsize=(16, 12))
|
| 157 |
-
|
| 158 |
-
# PC1 loadings
|
| 159 |
-
pc1_loadings = components_df['PC1'].sort_values(key=abs, ascending=False)
|
| 160 |
-
axes[0,0].barh(range(len(pc1_loadings)), pc1_loadings.values)
|
| 161 |
-
axes[0,0].set_yticks(range(len(pc1_loadings)))
|
| 162 |
-
axes[0,0].set_yticklabels(pc1_loadings.index, fontsize=9)
|
| 163 |
-
axes[0,0].set_title(f'PC1 Loadings (Explains {explained_variance[0]*100:.1f}% of variance)')
|
| 164 |
-
axes[0,0].axvline(x=0, color='black', linestyle='-', alpha=0.3)
|
| 165 |
-
|
| 166 |
-
# PC2 loadings
|
| 167 |
-
pc2_loadings = components_df['PC2'].sort_values(key=abs, ascending=False)
|
| 168 |
-
axes[0,1].barh(range(len(pc2_loadings)), pc2_loadings.values, color='orange')
|
| 169 |
-
axes[0,1].set_yticks(range(len(pc2_loadings)))
|
| 170 |
-
axes[0,1].set_yticklabels(pc2_loadings.index, fontsize=9)
|
| 171 |
-
axes[0,1].set_title(f'PC2 Loadings (Explains {explained_variance[1]*100:.1f}% of variance)')
|
| 172 |
-
axes[0,1].axvline(x=0, color='black', linestyle='-', alpha=0.3)
|
| 173 |
-
|
| 174 |
-
# PC3 loadings
|
| 175 |
-
pc3_loadings = components_df['PC3'].sort_values(key=abs, ascending=False)
|
| 176 |
-
axes[1,0].barh(range(len(pc3_loadings)), pc3_loadings.values, color='green')
|
| 177 |
-
axes[1,0].set_yticks(range(len(pc3_loadings)))
|
| 178 |
-
axes[1,0].set_yticklabels(pc3_loadings.index, fontsize=9)
|
| 179 |
-
axes[1,0].set_title(f'PC3 Loadings (Explains {explained_variance[2]*100:.1f}% of variance)')
|
| 180 |
-
axes[1,0].axvline(x=0, color='black', linestyle='-', alpha=0.3)
|
| 181 |
-
|
| 182 |
-
# PC1 vs PC2 scatter plot of cities
|
| 183 |
-
axes[1,1].scatter(pca_data[:, 0], pca_data[:, 1], alpha=0.6)
|
| 184 |
-
axes[1,1].set_xlabel('PC1')
|
| 185 |
-
axes[1,1].set_ylabel('PC2')
|
| 186 |
-
axes[1,1].set_title('Students in PC1-PC2 Space')
|
| 187 |
-
axes[1,1].grid(True, alpha=0.3)
|
| 188 |
-
|
| 189 |
-
# PC1 vs PC3 scatter plot of cities
|
| 190 |
-
axes[2,0].scatter(pca_data[:, 0], pca_data[:, 2], alpha=0.6)
|
| 191 |
-
axes[2,0].set_xlabel('PC1')
|
| 192 |
-
axes[2,0].set_ylabel('PC3')
|
| 193 |
-
axes[2,0].set_title('Students in PC1-PC3 Space')
|
| 194 |
-
axes[2,0].grid(True, alpha=0.3)
|
| 195 |
-
|
| 196 |
-
# PC2 vs PC3 scatter plot of cities
|
| 197 |
-
axes[2,1].scatter(pca_data[:, 1], pca_data[:, 2], alpha=0.6)
|
| 198 |
-
axes[2,1].set_xlabel('PC2')
|
| 199 |
-
axes[2,1].set_ylabel('PC3')
|
| 200 |
-
axes[2,1].set_title('Students in PC2-PC3 Space')
|
| 201 |
-
axes[2,1].grid(True, alpha=0.3)
|
| 202 |
-
plt.tight_layout()
|
| 203 |
-
st.pyplot(fig)
|
| 204 |
-
|
| 205 |
-
# KMeans clustering on PCA reduced data
|
| 206 |
-
kmeans = KMeans(n_clusters=k, random_state=42)
|
| 207 |
-
cluster_labels = kmeans.fit_predict(pca_data[:,:5]) # Using first 5 PCs
|
| 208 |
-
silhouette_avg = silhouette_score(pca_data[:,:5], cluster_labels)
|
| 209 |
-
st.write(f"Silhouette Score for k={k}: {silhouette_avg:.3f}")
|
| 210 |
-
pca_data_pd['Cluster'] = cluster_labels
|
| 211 |
-
pca = PCA(n_components=2, random_state=42)
|
| 212 |
-
pca_2d = pca.fit_transform(pca_data_pd.drop(columns=['Cluster']))
|
| 213 |
-
pca_2d_df = pd.DataFrame(pca_2d, columns=['PC1', 'PC2'])
|
| 214 |
-
pca_2d_df['Cluster'] = cluster_labels
|
| 215 |
-
st.write("2D PCA plot with KMeans clusters:")
|
| 216 |
-
|
| 217 |
-
kmeans_iteration_demo(pca_2d_df[['PC1', 'PC2']].values, k)
|
| 218 |
-
|
| 219 |
-
# ...existing code...
|
| 220 |
-
# ...existing code...
|
| 221 |
-
else:
|
| 222 |
-
st.write('You selected No dimensionality reduction')
|
| 223 |
-
st.write('The original data is shown below')
|
| 224 |
-
st.dataframe(data.head(10))
|
| 225 |
-
|
| 226 |
-
# Standardize the data
|
| 227 |
-
data_scaled = StandardScaler().fit_transform(data)
|
| 228 |
-
data_scaled_df = pd.DataFrame(data_scaled, columns=data.columns)
|
| 229 |
-
st.dataframe(data_scaled_df.head(10))
|
| 230 |
-
|
| 231 |
-
# KMeans clustering on original scaled data
|
| 232 |
-
kmeans = KMeans(n_clusters=k, random_state=seed)
|
| 233 |
-
cluster_labels = kmeans.fit_predict(data_scaled_df)
|
| 234 |
-
silhouette_avg = silhouette_score(data_scaled_df, cluster_labels)
|
| 235 |
-
st.write(f"Silhouette Score for k={k}: {silhouette_avg:.3f}")
|
| 236 |
-
|
| 237 |
-
# Add cluster labels for plotting
|
| 238 |
-
data_scaled_df['Cluster'] = cluster_labels
|
| 239 |
-
|
| 240 |
-
# 2D scatter plot using two original features for visualization
|
| 241 |
-
fig, ax = plt.subplots(figsize=(8, 6))
|
| 242 |
-
scatter = ax.scatter(
|
| 243 |
-
data_scaled_df[feature_x], data_scaled_df[feature_y],
|
| 244 |
-
c=cluster_labels, cmap='tab10', alpha=0.7, s=50
|
| 245 |
-
)
|
| 246 |
-
ax.set_xlabel(feature_x)
|
| 247 |
-
ax.set_ylabel(feature_y)
|
| 248 |
-
ax.set_title('KMeans Clusters (Original Scaled Features)')
|
| 249 |
-
plt.colorbar(scatter, ax=ax, label='Cluster')
|
| 250 |
-
st.pyplot(fig)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|