Update data_processor.py
Browse files- data_processor.py +83 -3
data_processor.py
CHANGED
|
@@ -243,9 +243,89 @@ class DataProcessor:
|
|
| 243 |
'Total Number of Days Available': [total_days]
|
| 244 |
})
|
| 245 |
|
| 246 |
-
def compute_student_metrics(self):
|
| 247 |
-
|
| 248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
|
| 250 |
def evaluate_student(self, row, attendance_threshold=90, engagement_threshold=80):
|
| 251 |
if row["Attended ≥ 90%"] == "No":
|
|
|
|
| 243 |
'Total Number of Days Available': [total_days]
|
| 244 |
})
|
| 245 |
|
| 246 |
+
def compute_student_metrics(self, df):
|
| 247 |
+
intervention_df = df[df[self.INTERVENTION_COLUMN].str.strip().str.lower() == 'yes']
|
| 248 |
+
intervention_sessions_held = len(intervention_df)
|
| 249 |
+
student_columns = [col for col in df.columns if col.startswith('Student Attendance')]
|
| 250 |
+
|
| 251 |
+
student_metrics = {}
|
| 252 |
+
for col in student_columns:
|
| 253 |
+
student_name = col.replace('Student Attendance [', '').replace(']', '').strip()
|
| 254 |
+
student_data = intervention_df[[col]].copy()
|
| 255 |
+
student_data[col] = student_data[col].fillna('Absent')
|
| 256 |
+
|
| 257 |
+
attendance_values = student_data[col].apply(lambda x: 1 if x in [
|
| 258 |
+
self.ENGAGED_STR,
|
| 259 |
+
self.PARTIALLY_ENGAGED_STR,
|
| 260 |
+
self.NOT_ENGAGED_STR
|
| 261 |
+
] else 0)
|
| 262 |
+
|
| 263 |
+
sessions_attended = attendance_values.sum()
|
| 264 |
+
attendance_pct = (sessions_attended / intervention_sessions_held) * 100 if intervention_sessions_held > 0 else 0
|
| 265 |
+
attendance_pct = round(attendance_pct)
|
| 266 |
+
|
| 267 |
+
engagement_counts = {
|
| 268 |
+
'Engaged': 0,
|
| 269 |
+
'Partially Engaged': 0,
|
| 270 |
+
'Not Engaged': 0,
|
| 271 |
+
'Absent': 0
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
for x in student_data[col]:
|
| 275 |
+
if x == self.ENGAGED_STR:
|
| 276 |
+
engagement_counts['Engaged'] += 1
|
| 277 |
+
elif x == self.PARTIALLY_ENGAGED_STR:
|
| 278 |
+
engagement_counts['Partially Engaged'] += 1
|
| 279 |
+
elif x == self.NOT_ENGAGED_STR:
|
| 280 |
+
engagement_counts['Not Engaged'] += 1
|
| 281 |
+
else:
|
| 282 |
+
engagement_counts['Absent'] += 1 # Count as Absent if not engaged
|
| 283 |
+
|
| 284 |
+
# Calculate percentages for engagement states
|
| 285 |
+
total_sessions = sum(engagement_counts.values())
|
| 286 |
+
|
| 287 |
+
# Engagement (%)
|
| 288 |
+
engagement_pct = (engagement_counts['Engaged'] / total_sessions * 100) if total_sessions > 0 else 0
|
| 289 |
+
engagement_pct = round(engagement_pct)
|
| 290 |
+
|
| 291 |
+
engaged_pct = (engagement_counts['Engaged'] / total_sessions * 100) if total_sessions > 0 else 0
|
| 292 |
+
engaged_pct = round(engaged_pct)
|
| 293 |
+
|
| 294 |
+
partially_engaged_pct = (engagement_counts['Partially Engaged'] / total_sessions * 100) if total_sessions > 0 else 0
|
| 295 |
+
partially_engaged_pct = round(partially_engaged_pct)
|
| 296 |
+
|
| 297 |
+
not_engaged_pct = (engagement_counts['Not Engaged'] / total_sessions * 100) if total_sessions > 0 else 0
|
| 298 |
+
not_engaged_pct = round(not_engaged_pct)
|
| 299 |
+
|
| 300 |
+
absent_pct = (engagement_counts['Absent'] / total_sessions * 100) if total_sessions > 0 else 0
|
| 301 |
+
absent_pct = round(absent_pct)
|
| 302 |
+
|
| 303 |
+
# Store metrics in the required order
|
| 304 |
+
student_metrics[student_name] = {
|
| 305 |
+
'Attendance (%)': attendance_pct,
|
| 306 |
+
'Attendance #': sessions_attended, # Raw number of sessions attended
|
| 307 |
+
'Engagement (%)': engagement_pct,
|
| 308 |
+
'Engaged (%)': engaged_pct,
|
| 309 |
+
'Partially Engaged (%)': partially_engaged_pct,
|
| 310 |
+
'Not Engaged (%)': not_engaged_pct,
|
| 311 |
+
'Absent (%)': absent_pct
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
# Create a DataFrame from student_metrics
|
| 315 |
+
student_metrics_df = pd.DataFrame.from_dict(student_metrics, orient='index').reset_index()
|
| 316 |
+
student_metrics_df.rename(columns={'index': 'Student'}, inplace=True)
|
| 317 |
+
return student_metrics_df
|
| 318 |
+
|
| 319 |
+
def compute_average_metrics(self, student_metrics_df):
|
| 320 |
+
# Calculate the attendance and engagement average percentages across students
|
| 321 |
+
attendance_avg_stats = student_metrics_df['Attendance (%)'].mean() # Calculate the average attendance percentage
|
| 322 |
+
engagement_avg_stats = student_metrics_df['Engagement (%)'].mean() # Calculate the average engagement percentage
|
| 323 |
+
|
| 324 |
+
# Round the averages to make them whole numbers
|
| 325 |
+
attendance_avg_stats = round(attendance_avg_stats)
|
| 326 |
+
engagement_avg_stats = round(engagement_avg_stats)
|
| 327 |
+
|
| 328 |
+
return attendance_avg_stats, engagement_avg_stats
|
| 329 |
|
| 330 |
def evaluate_student(self, row, attendance_threshold=90, engagement_threshold=80):
|
| 331 |
if row["Attended ≥ 90%"] == "No":
|