Rittik101/Sstudize
0
1import streamlit as st2import pandas as pd3import matplotlib.pyplot as plt4import seaborn as sns5import numpy as np6 7# Load data from the CSV file8data = pd.read_csv('https://raw.githubusercontent.com/forittik/test_analysis_100_updated/refs/heads/main/final_mereged_data.csv')9 10# Set up constants11CORRECT_MARK = 412WRONG_MARK = -113UNATTEMPTED_MARK = 014 15# Define question ranges for each subject16PHYSICS_REQUIRED = list(range(1, 21)) # Questions 1-2017PHYSICS_OPTIONAL = list(range(21, 31)) # Questions 21-3018 19CHEMISTRY_REQUIRED = list(range(31, 51)) # Questions 31-5020CHEMISTRY_OPTIONAL = list(range(51, 61)) # Questions 51-6021 22MATHEMATICS_REQUIRED = list(range(61, 81)) # Questions 61-8023MATHEMATICS_OPTIONAL = list(range(81, 91)) # Questions 81-9024 25# Function to calculate scores based on rules26def calculate_subject_score(data, student_id, required_questions, optional_questions):27 score = 028 29 # Calculate required questions score30 for q in required_questions:31 if q in data['Question_no'].values:32 correct_answer = data.loc[data['Question_no'] == q, 'correct_answer_key'].values[0]33 student_answer = data.loc[data['Question_no'] == q, student_id].values[0]34 35 if student_answer == correct_answer:36 score += CORRECT_MARK37 elif pd.isna(student_answer):38 score += UNATTEMPTED_MARK39 else:40 score += WRONG_MARK41 42 # Calculate optional questions score43 optional_attempts = []44 for q in optional_questions:45 if q in data['Question_no'].values:46 student_answer = data.loc[data['Question_no'] == q, student_id].values[0]47 if not pd.isna(student_answer):48 optional_attempts.append((q, student_answer))49 50 for q, student_answer in optional_attempts:51 correct_answer = data.loc[data['Question_no'] == q, 'correct_answer_key'].values[0]52 score += CORRECT_MARK if student_answer == correct_answer else WRONG_MARK53 54 return min(score, 100)55 56# Streamlit UI57st.title("JEE Mock Test Score Analysis")58 59# Select multiple student IDs60student_ids = st.multiselect("Select Student IDs", options=data.columns[3:])61 62if student_ids:63 physics_scores = []64 chemistry_scores = []65 mathematics_scores = []66 total_scores = []67 68 # Loop through selected students and calculate scores69 for student_id in student_ids:70 physics_score = calculate_subject_score(data, student_id, PHYSICS_REQUIRED, PHYSICS_OPTIONAL)71 chemistry_score = calculate_subject_score(data, student_id, CHEMISTRY_REQUIRED, CHEMISTRY_OPTIONAL)72 mathematics_score = calculate_subject_score(data, student_id, MATHEMATICS_REQUIRED, MATHEMATICS_OPTIONAL)73 74 physics_scores.append(physics_score)75 chemistry_scores.append(chemistry_score)76 mathematics_scores.append(mathematics_score)77 total_scores.append(physics_score + chemistry_score + mathematics_score)78 79 # Display score format for each selected student80 for i, student_id in enumerate(student_ids):81 st.subheader(f"Scores of {student_id}")82 st.write(f"Physics Score: {physics_scores[i]}")83 st.write(f"Chemistry Score: {chemistry_scores[i]}")84 st.write(f"Mathematics Score: {mathematics_scores[i]}")85 st.write(f"Total Score: {total_scores[i]} / 300")86 st.write("---")87 88 # The rest of your existing code for plotting can remain as it is89 90 91 all_student_columns = data.columns[3:]92 all_total_scores = [93 calculate_subject_score(data, student_id, PHYSICS_REQUIRED, PHYSICS_OPTIONAL) +94 calculate_subject_score(data, student_id, CHEMISTRY_REQUIRED, CHEMISTRY_OPTIONAL) +95 calculate_subject_score(data, student_id, MATHEMATICS_REQUIRED, MATHEMATICS_OPTIONAL)96 for student_id in all_student_columns97 ]98 avg_all_students = np.mean(all_total_scores)99 avg_selected_students = np.mean(total_scores)100 101 # Total Score Distribution - Bar Plot with Average Lines102 st.subheader("Total Score Distribution (Bar Plot)")103 plt.figure(figsize=(10, 6))104 plt.bar(student_ids, total_scores, color='purple', label='Total Scores')105 plt.axhline(avg_all_students, color='red', linestyle='--', linewidth=1.5, label='Average for All Students')106 plt.axhline(avg_selected_students, color='blue', linestyle='--', linewidth=1.5, label='Average for Selected Students')107 plt.text(len(student_ids) - 0.5, avg_all_students + 5, f"{avg_all_students:.2f}", color='red', ha='center', fontweight='bold')108 plt.text(len(student_ids) - 0.5, avg_selected_students + 5, f"{avg_selected_students:.2f}", color='blue', ha='center', fontweight='bold')109 plt.xlabel("Student IDs")110 plt.ylabel("Total Score")111 plt.title("Total Score Comparison Across Students")112 plt.ylim(0, 300)113 plt.legend()114 st.pyplot(plt)115 116 # Subject-wise Average Comparison Plot117 st.subheader("Subject-wise Average Scores (Selected vs All Students)")118 avg_physics_all_students = np.mean([119 calculate_subject_score(data, student_id, PHYSICS_REQUIRED, PHYSICS_OPTIONAL)120 for student_id in all_student_columns121 ])122 avg_chemistry_all_students = np.mean([123 calculate_subject_score(data, student_id, CHEMISTRY_REQUIRED, CHEMISTRY_OPTIONAL)124 for student_id in all_student_columns125 ])126 avg_mathematics_all_students = np.mean([127 calculate_subject_score(data, student_id, MATHEMATICS_REQUIRED, MATHEMATICS_OPTIONAL)128 for student_id in all_student_columns129 ])130 131 avg_physics_selected = np.mean(physics_scores)132 avg_chemistry_selected = np.mean(chemistry_scores)133 avg_mathematics_selected = np.mean(mathematics_scores)134 135 subjects = ['Physics', 'Chemistry', 'Mathematics']136 avg_all_students = [avg_physics_all_students, avg_chemistry_all_students, avg_mathematics_all_students]137 avg_selected_students = [avg_physics_selected, avg_chemistry_selected, avg_mathematics_selected]138 139 x = np.arange(len(subjects))140 width = 0.35141 142 fig, ax = plt.subplots(figsize=(10, 6))143 bars1 = ax.bar(x - width/2, avg_all_students, width, label='All Students', color='skyblue')144 bars2 = ax.bar(x + width/2, avg_selected_students, width, label='Selected Students', color='orange')145 146 for bar in bars1:147 ax.text(148 bar.get_x() + bar.get_width() / 2,149 bar.get_height() + 2,150 f'{bar.get_height():.2f}',151 ha='center', color='black', fontweight='bold'152 )153 154 for bar in bars2:155 ax.text(156 bar.get_x() + bar.get_width() / 2,157 bar.get_height() + 2,158 f'{bar.get_height():.2f}',159 ha='center', color='black', fontweight='bold'160 )161 162 ax.set_xlabel("Subjects")163 ax.set_ylabel("Average Scores")164 ax.set_title("Average Scores by Subject for All Students vs Selected Students")165 ax.set_xticks(x)166 ax.set_xticklabels(subjects)167 ax.legend()168 st.pyplot(fig)169 170 # Subject-wise Performance Comparison - Side-by-Side Column Chart171 st.subheader("Subject-wise Performance Comparison (Side-by-Side Column Chart)")172 173 # Ensure the lists match the length of student_ids174 if len(student_ids) == len(physics_scores) == len(chemistry_scores) == len(mathematics_scores):175 subjects = ['Physics', 'Chemistry', 'Mathematics']176 subject_scores = [physics_scores, chemistry_scores, mathematics_scores]177 178 # Create a side-by-side bar chart179 width = 0.25 # Width of bars180 x = np.arange(len(student_ids)) # Position of bars on x-axis181 182 fig, ax = plt.subplots(figsize=(10, 6))183 ax.bar(x - width, physics_scores, width, label='Physics', color='blue')184 ax.bar(x, chemistry_scores, width, label='Chemistry', color='green')185 ax.bar(x + width, mathematics_scores, width, label='Mathematics', color='orange')186 187 # Label the bars with their scores188 for i, v in enumerate(physics_scores):189 ax.text(x[i] - width, v + 1, str(v), ha='center', fontweight='bold')190 for i, v in enumerate(chemistry_scores):191 ax.text(x[i], v + 1, str(v), ha='center', fontweight='bold')192 for i, v in enumerate(mathematics_scores):193 ax.text(x[i] + width, v + 1, str(v), ha='center', fontweight='bold')194 195 ax.set_xlabel("Student IDs")196 ax.set_ylabel("Scores")197 ax.set_title("Subject-wise Scores (Side-by-Side Comparison)")198 ax.set_xticks(x)199 ax.set_xticklabels(student_ids)200 ax.legend()201 st.pyplot(fig)202 203 # Chapter-wise Average Score Analysis204 # Chapter-wise Average Score Analysis205 # Chapter-wise Average Score Analysis206st.subheader("Chapter-wise Average Score Analysis")207 208# Create a dictionary to store chapter-wise scores209chapter_scores = {}210chapter_question_counts = {}211 212# Iterate through the questions in the data and calculate the scores for each chapter213for student_id in student_ids:214 for q in data['Question_no']:215 # Get the chapter name directly from the 'Chapter_name' column216 chapter = data.loc[data['Question_no'] == q, 'Chapter_name'].values[0]217 correct_answer = data.loc[data['Question_no'] == q, 'correct_answer_key'].values[0]218 student_answer = data.loc[data['Question_no'] == q, student_id].values[0]219 220 # Update chapter scores and counts221 if chapter not in chapter_scores:222 chapter_scores[chapter] = 0223 chapter_question_counts[chapter] = 0224 225 if student_answer == correct_answer:226 chapter_scores[chapter] += CORRECT_MARK227 elif pd.isna(student_answer):228 chapter_scores[chapter] += UNATTEMPTED_MARK229 else:230 chapter_scores[chapter] += WRONG_MARK231 232 chapter_question_counts[chapter] += 1233 234# Calculate average score per chapter235chapter_avg_scores = {236 chapter: chapter_scores[chapter] / chapter_question_counts[chapter] 237 for chapter in chapter_scores238}239 240# Plot Chapter-wise Average Scores241chapters = list(chapter_avg_scores.keys())242avg_scores = list(chapter_avg_scores.values())243 244fig, ax = plt.subplots(figsize=(10, 6))245ax.barh(chapters, avg_scores, color='teal')246 247ax.set_xlabel("Average Score")248ax.set_ylabel("Chapters")249ax.set_title("Chapter-wise Average Scores")250 251# Display the plot252st.pyplot(fig)253 254# Chapter-wise Question Distribution for Physics, Chemistry, and Mathematics255st.subheader("Chapter-wise Question Distribution for Physics, Chemistry, and Mathematics")256 257# Function to calculate the number of questions per chapter for each subject258import streamlit as st259import matplotlib.pyplot as plt260 261# Function to calculate the number of questions per chapter for each subject262import streamlit as st263import matplotlib.pyplot as plt264 265# Function to calculate the number of questions per chapter for each subject266def chapter_question_distribution(subject_required, subject_optional):267 # Combine required and optional questions for the subject268 subject_questions = subject_required + subject_optional269 chapter_counts = {}270 271 for q in subject_questions:272 if q in data['Question_no'].values:273 chapter = data.loc[data['Question_no'] == q, 'Chapter_name'].values[0]274 if chapter not in chapter_counts:275 chapter_counts[chapter] = 0276 chapter_counts[chapter] += 1277 278 return chapter_counts279 280# Get chapter-wise question distribution for each subject281physics_chapter_distribution = chapter_question_distribution(PHYSICS_REQUIRED, PHYSICS_OPTIONAL)282chemistry_chapter_distribution = chapter_question_distribution(CHEMISTRY_REQUIRED, CHEMISTRY_OPTIONAL)283mathematics_chapter_distribution = chapter_question_distribution(MATHEMATICS_REQUIRED, MATHEMATICS_OPTIONAL)284 285# List of subjects and their respective chapter distributions286subjects = ['Physics', 'Chemistry', 'Mathematics']287chapter_distributions = [physics_chapter_distribution, chemistry_chapter_distribution, mathematics_chapter_distribution]288 289# Streamlit UI for subject navigation290subject_selection = st.selectbox("Select Subject", options=subjects)291 292# Determine which subject's chapter distribution to plot293if subject_selection == 'Physics':294 chapter_distribution = physics_chapter_distribution295elif subject_selection == 'Chemistry':296 chapter_distribution = chemistry_chapter_distribution297else:298 chapter_distribution = mathematics_chapter_distribution299 300# Plot the selected subject's chapter distribution301fig, ax = plt.subplots(figsize=(10, 6))302 303ax.bar(chapter_distribution.keys(), chapter_distribution.values(), color='teal')304ax.set_title(f"{subject_selection} Chapter-wise Question Distribution")305ax.set_xlabel("Chapters")306ax.set_ylabel("Number of Questions")307 308# Rotate x-axis labels and align them309ax.set_xticklabels(chapter_distribution.keys(), rotation=45, ha='right')310 311# Display the plot312st.pyplot(fig)