Dun3Co commited on
Commit
cf5ff90
·
verified ·
1 Parent(s): 075c6e9

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +250 -0
app.py ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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)