mirror of
https://github.com/andwati/predictive_analysis.git
synced 2026-10-18 08:42:52 +00:00
Refactor Streamlit app for improved UI and user experience; updated titles, added quick presets, and enhanced input forms.
This commit is contained in:
+111
-56
@@ -13,8 +13,8 @@ from plotly.subplots import make_subplots
|
||||
|
||||
# Configure Streamlit page
|
||||
st.set_page_config(
|
||||
page_title="🎓 Student Success Predictor",
|
||||
page_icon="🎓",
|
||||
page_title="Student Success Predictor",
|
||||
page_icon="📊",
|
||||
layout="wide",
|
||||
initial_sidebar_state="expanded"
|
||||
)
|
||||
@@ -251,42 +251,62 @@ def main():
|
||||
feature_maps = create_feature_mappings()
|
||||
|
||||
# Header
|
||||
st.markdown('<h1 class="main-header">🎓 Student Success Predictor</h1>', unsafe_allow_html=True)
|
||||
st.markdown('<h1 class="main-header">Student Success Predictor</h1>', unsafe_allow_html=True)
|
||||
st.markdown("**Predict whether a student will Graduate, Dropout, or remain Enrolled based on academic and demographic factors.**")
|
||||
|
||||
# Sidebar for input
|
||||
st.sidebar.markdown('<h2 class="sub-header">📝 Student Information</h2>', unsafe_allow_html=True)
|
||||
st.sidebar.markdown('<h2 class="sub-header">Student Information</h2>', unsafe_allow_html=True)
|
||||
|
||||
# Create input form
|
||||
with st.sidebar:
|
||||
# Quick presets
|
||||
st.markdown("### Quick Start")
|
||||
preset = st.selectbox("Load Sample Data",
|
||||
["Custom Entry", "Typical Graduate Student", "At-Risk Student", "International Student"],
|
||||
help="Choose a preset to quickly fill common scenarios")
|
||||
|
||||
# Set default values based on preset
|
||||
defaults = {
|
||||
"Custom Entry": {"age": 20, "gender": 0, "marital": 1, "app_mode": 1, "course": 9254, "prev_grade": 120, "adm_grade": 120},
|
||||
"Typical Graduate Student": {"age": 19, "gender": 1, "marital": 1, "app_mode": 15, "course": 9254, "prev_grade": 160, "adm_grade": 142},
|
||||
"At-Risk Student": {"age": 22, "gender": 1, "marital": 1, "app_mode": 17, "course": 171, "prev_grade": 100, "adm_grade": 110},
|
||||
"International Student": {"age": 21, "gender": 0, "marital": 1, "app_mode": 1, "course": 9238, "prev_grade": 135, "adm_grade": 130}
|
||||
}
|
||||
|
||||
if preset != "Custom Entry":
|
||||
st.info(f"Loading {preset} preset values. You can modify any field below.")
|
||||
|
||||
# Personal Information
|
||||
st.markdown("### 👤 Personal Information")
|
||||
st.markdown("### Personal Information")
|
||||
|
||||
marital_status = st.selectbox(
|
||||
"Marital Status",
|
||||
options=list(feature_maps['marital_status'].keys()),
|
||||
format_func=lambda x: feature_maps['marital_status'][x]
|
||||
format_func=lambda x: feature_maps['marital_status'][x],
|
||||
index=list(feature_maps['marital_status'].keys()).index(defaults[preset]["marital"])
|
||||
)
|
||||
|
||||
gender = st.selectbox("Gender", [0, 1], format_func=lambda x: "Female" if x == 0 else "Male")
|
||||
age_at_enrollment = st.slider("Age at Enrollment", 17, 70, 20)
|
||||
nationality = st.selectbox("Nationality", [1, 2, 6, 11, 13, 14, 17, 21, 22, 24, 25, 26, 32, 41, 62, 100, 101, 103, 105, 108, 109])
|
||||
gender = st.selectbox("Gender", [0, 1], format_func=lambda x: "Female" if x == 0 else "Male", index=defaults[preset]["gender"])
|
||||
age_at_enrollment = st.number_input("Age at Enrollment", min_value=17, max_value=70, value=defaults[preset]["age"], step=1)
|
||||
nationality = st.selectbox("Nationality", [1, 2, 6, 11, 13, 14, 17, 21, 22, 24, 25, 26, 32, 41, 62, 100, 101, 103, 105, 108, 109], index=0)
|
||||
|
||||
# Academic Background
|
||||
st.markdown("### 🎓 Academic Background")
|
||||
st.markdown("### Academic Background")
|
||||
|
||||
application_mode = st.selectbox(
|
||||
"Application Mode",
|
||||
options=list(feature_maps['application_mode'].keys()),
|
||||
format_func=lambda x: feature_maps['application_mode'].get(x, f"Mode {x}")
|
||||
format_func=lambda x: feature_maps['application_mode'].get(x, f"Mode {x}"),
|
||||
index=list(feature_maps['application_mode'].keys()).index(defaults[preset]["app_mode"]) if defaults[preset]["app_mode"] in feature_maps['application_mode'] else 0
|
||||
)
|
||||
|
||||
application_order = st.slider("Application Order", 0, 9, 1)
|
||||
application_order = st.selectbox("Application Order (1st choice, 2nd choice, etc.)", [1, 2, 3, 4, 5, 6, 7, 8, 9], index=0)
|
||||
|
||||
course = st.selectbox(
|
||||
"Course",
|
||||
options=list(feature_maps['course'].keys()),
|
||||
format_func=lambda x: feature_maps['course'].get(x, f"Course {x}")
|
||||
format_func=lambda x: feature_maps['course'].get(x, f"Course {x}"),
|
||||
index=list(feature_maps['course'].keys()).index(defaults[preset]["course"]) if defaults[preset]["course"] in feature_maps['course'] else 0
|
||||
)
|
||||
|
||||
daytime_evening = st.selectbox("Attendance", [0, 1], format_func=lambda x: "Evening" if x == 0 else "Daytime")
|
||||
@@ -297,11 +317,14 @@ def main():
|
||||
format_func=lambda x: feature_maps['qualification'].get(x, f"Qualification {x}")
|
||||
)
|
||||
|
||||
previous_qualification_grade = st.slider("Previous Qualification Grade", 95, 190, 120)
|
||||
admission_grade = st.slider("Admission Grade", 95, 190, 120)
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
previous_qualification_grade = st.number_input("Previous Qualification Grade", min_value=95, max_value=190, value=defaults[preset]["prev_grade"], step=1)
|
||||
with col2:
|
||||
admission_grade = st.number_input("Admission Grade", min_value=95, max_value=190, value=defaults[preset]["adm_grade"], step=1)
|
||||
|
||||
# Family Background
|
||||
st.markdown("### 👨👩👧👦 Family Background")
|
||||
st.markdown("### Family Background")
|
||||
|
||||
mothers_qualification = st.selectbox(
|
||||
"Mother's Qualification",
|
||||
@@ -328,41 +351,73 @@ def main():
|
||||
)
|
||||
|
||||
# Financial and Social Factors
|
||||
st.markdown("### 💰 Financial & Social")
|
||||
st.markdown("### Financial & Social")
|
||||
|
||||
displaced = st.selectbox("Displaced", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes")
|
||||
educational_special_needs = st.selectbox("Educational Special Needs", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes")
|
||||
debtor = st.selectbox("Debtor", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes")
|
||||
tuition_fees_up_to_date = st.selectbox("Tuition Fees Up to Date", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes")
|
||||
scholarship_holder = st.selectbox("Scholarship Holder", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes")
|
||||
international = st.selectbox("International Student", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
displaced = st.radio("Displaced Student", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes", horizontal=True)
|
||||
educational_special_needs = st.radio("Educational Special Needs", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes", horizontal=True)
|
||||
debtor = st.radio("Has Outstanding Debts", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes", horizontal=True)
|
||||
with col2:
|
||||
tuition_fees_up_to_date = st.radio("Tuition Fees Up to Date", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes", horizontal=True)
|
||||
scholarship_holder = st.radio("Scholarship Holder", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes", horizontal=True)
|
||||
international = st.radio("International Student", [0, 1], format_func=lambda x: "No" if x == 0 else "Yes", horizontal=True)
|
||||
|
||||
# Academic Performance - 1st Semester
|
||||
st.markdown("### 📚 1st Semester Performance")
|
||||
st.markdown("### 1st Semester Performance")
|
||||
st.caption("Enter the student's academic performance for their first semester")
|
||||
|
||||
curricular_units_1st_sem_credited = st.slider("Curricular Units 1st Sem (Credited)", 0, 26, 0)
|
||||
curricular_units_1st_sem_enrolled = st.slider("Curricular Units 1st Sem (Enrolled)", 0, 26, 6)
|
||||
curricular_units_1st_sem_evaluations = st.slider("Curricular Units 1st Sem (Evaluations)", 0, 45, 6)
|
||||
curricular_units_1st_sem_approved = st.slider("Curricular Units 1st Sem (Approved)", 0, 26, 6)
|
||||
curricular_units_1st_sem_grade = st.slider("Curricular Units 1st Sem (Grade)", 0, 20, 13)
|
||||
curricular_units_1st_sem_without_evaluations = st.slider("Curricular Units 1st Sem (Without Evaluations)", 0, 14, 0)
|
||||
# Set default academic values based on preset
|
||||
first_sem_defaults = {
|
||||
"Custom Entry": {"enrolled": 6, "approved": 6, "grade": 13, "credited": 0, "evaluations": 6, "without": 0},
|
||||
"Typical Graduate Student": {"enrolled": 6, "approved": 6, "grade": 14, "credited": 0, "evaluations": 6, "without": 0},
|
||||
"At-Risk Student": {"enrolled": 6, "approved": 0, "grade": 0, "credited": 0, "evaluations": 0, "without": 0},
|
||||
"International Student": {"enrolled": 6, "approved": 6, "grade": 13, "credited": 0, "evaluations": 6, "without": 0}
|
||||
}
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
curricular_units_1st_sem_enrolled = st.number_input("Enrolled Units", min_value=0, max_value=26, value=first_sem_defaults[preset]["enrolled"], step=1, key="1st_enrolled", help="Number of courses registered for")
|
||||
curricular_units_1st_sem_approved = st.number_input("Approved Units", min_value=0, max_value=26, value=first_sem_defaults[preset]["approved"], step=1, key="1st_approved", help="Number of courses passed")
|
||||
curricular_units_1st_sem_credited = st.number_input("Credited Units", min_value=0, max_value=26, value=first_sem_defaults[preset]["credited"], step=1, key="1st_credited", help="Credits from previous education")
|
||||
with col2:
|
||||
curricular_units_1st_sem_evaluations = st.number_input("Evaluations", min_value=0, max_value=45, value=first_sem_defaults[preset]["evaluations"], step=1, key="1st_evaluations", help="Number of exams taken")
|
||||
curricular_units_1st_sem_grade = st.number_input("Average Grade (0-20)", min_value=0, max_value=20, value=first_sem_defaults[preset]["grade"], step=1, key="1st_grade", help="Average grade on 0-20 scale")
|
||||
curricular_units_1st_sem_without_evaluations = st.number_input("Without Evaluations", min_value=0, max_value=14, value=first_sem_defaults[preset]["without"], step=1, key="1st_without", help="Courses registered but not evaluated")
|
||||
|
||||
# Academic Performance - 2nd Semester
|
||||
st.markdown("### 📖 2nd Semester Performance")
|
||||
st.markdown("### 2nd Semester Performance")
|
||||
st.caption("Enter the student's academic performance for their second semester")
|
||||
|
||||
curricular_units_2nd_sem_credited = st.slider("Curricular Units 2nd Sem (Credited)", 0, 20, 0)
|
||||
curricular_units_2nd_sem_enrolled = st.slider("Curricular Units 2nd Sem (Enrolled)", 0, 23, 6)
|
||||
curricular_units_2nd_sem_evaluations = st.slider("Curricular Units 2nd Sem (Evaluations)", 0, 33, 6)
|
||||
curricular_units_2nd_sem_approved = st.slider("Curricular Units 2nd Sem (Approved)", 0, 20, 6)
|
||||
curricular_units_2nd_sem_grade = st.slider("Curricular Units 2nd Sem (Grade)", 0, 20, 13)
|
||||
curricular_units_2nd_sem_without_evaluations = st.slider("Curricular Units 2nd Sem (Without Evaluations)", 0, 12, 0)
|
||||
# Set default academic values for 2nd semester based on preset
|
||||
second_sem_defaults = {
|
||||
"Custom Entry": {"enrolled": 6, "approved": 6, "grade": 13, "credited": 0, "evaluations": 6, "without": 0},
|
||||
"Typical Graduate Student": {"enrolled": 6, "approved": 6, "grade": 14, "credited": 0, "evaluations": 6, "without": 0},
|
||||
"At-Risk Student": {"enrolled": 6, "approved": 0, "grade": 0, "credited": 0, "evaluations": 0, "without": 0},
|
||||
"International Student": {"enrolled": 6, "approved": 6, "grade": 14, "credited": 0, "evaluations": 6, "without": 0}
|
||||
}
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
curricular_units_2nd_sem_enrolled = st.number_input("Enrolled Units", min_value=0, max_value=23, value=second_sem_defaults[preset]["enrolled"], step=1, key="2nd_enrolled", help="Number of courses registered for")
|
||||
curricular_units_2nd_sem_approved = st.number_input("Approved Units", min_value=0, max_value=20, value=second_sem_defaults[preset]["approved"], step=1, key="2nd_approved", help="Number of courses passed")
|
||||
curricular_units_2nd_sem_credited = st.number_input("Credited Units", min_value=0, max_value=20, value=second_sem_defaults[preset]["credited"], step=1, key="2nd_credited", help="Credits from previous education")
|
||||
with col2:
|
||||
curricular_units_2nd_sem_evaluations = st.number_input("Evaluations", min_value=0, max_value=33, value=second_sem_defaults[preset]["evaluations"], step=1, key="2nd_evaluations", help="Number of exams taken")
|
||||
curricular_units_2nd_sem_grade = st.number_input("Average Grade (0-20)", min_value=0, max_value=20, value=second_sem_defaults[preset]["grade"], step=1, key="2nd_grade", help="Average grade on 0-20 scale")
|
||||
curricular_units_2nd_sem_without_evaluations = st.number_input("Without Evaluations", min_value=0, max_value=12, value=second_sem_defaults[preset]["without"], step=1, key="2nd_without", help="Courses registered but not evaluated")
|
||||
|
||||
# Economic Indicators
|
||||
st.markdown("### 📊 Economic Indicators")
|
||||
st.markdown("### Economic Indicators")
|
||||
st.caption("These are typically set by the institution based on current economic conditions")
|
||||
|
||||
unemployment_rate = st.slider("Unemployment Rate (%)", 7.0, 16.2, 10.8)
|
||||
inflation_rate = st.slider("Inflation Rate (%)", -0.8, 3.7, 1.4)
|
||||
gdp = st.slider("GDP", -4.06, 3.51, 1.74)
|
||||
col1, col2, col3 = st.columns(3)
|
||||
with col1:
|
||||
unemployment_rate = st.number_input("Unemployment Rate (%)", min_value=7.0, max_value=16.2, value=10.8, step=0.1, format="%.1f")
|
||||
with col2:
|
||||
inflation_rate = st.number_input("Inflation Rate (%)", min_value=-0.8, max_value=3.7, value=1.4, step=0.1, format="%.1f")
|
||||
with col3:
|
||||
gdp = st.number_input("GDP Growth", min_value=-4.06, max_value=3.51, value=1.74, step=0.1, format="%.2f")
|
||||
|
||||
# Create user input dictionary
|
||||
user_input = {
|
||||
@@ -408,10 +463,10 @@ def main():
|
||||
col1, col2 = st.columns([2, 1])
|
||||
|
||||
with col1:
|
||||
st.markdown('<h2 class="sub-header">🔮 Prediction Results</h2>', unsafe_allow_html=True)
|
||||
st.markdown('<h2 class="sub-header">Prediction Results</h2>', unsafe_allow_html=True)
|
||||
|
||||
# Make prediction
|
||||
if st.button("🚀 Predict Student Outcome", type="primary"):
|
||||
if st.button("Predict Student Outcome", type="primary"):
|
||||
with st.spinner("Analyzing student data..."):
|
||||
# Preprocess input
|
||||
processed_input = preprocess_input(user_input, preprocessing_info)
|
||||
@@ -426,14 +481,14 @@ def main():
|
||||
|
||||
# Display prediction with styling
|
||||
if predicted_outcome == "Graduate":
|
||||
st.markdown(f'<div class="prediction-box graduate-box">🎓 Predicted Outcome: GRADUATE</div>', unsafe_allow_html=True)
|
||||
st.markdown(f'<div class="prediction-box graduate-box">Predicted Outcome: GRADUATE</div>', unsafe_allow_html=True)
|
||||
elif predicted_outcome == "Dropout":
|
||||
st.markdown(f'<div class="prediction-box dropout-box">⚠️ Predicted Outcome: DROPOUT</div>', unsafe_allow_html=True)
|
||||
st.markdown(f'<div class="prediction-box dropout-box">Predicted Outcome: DROPOUT</div>', unsafe_allow_html=True)
|
||||
else:
|
||||
st.markdown(f'<div class="prediction-box enrolled-box">📚 Predicted Outcome: ENROLLED</div>', unsafe_allow_html=True)
|
||||
st.markdown(f'<div class="prediction-box enrolled-box">Predicted Outcome: ENROLLED</div>', unsafe_allow_html=True)
|
||||
|
||||
# Display probabilities
|
||||
st.markdown("### 📊 Prediction Confidence")
|
||||
st.markdown("### Prediction Confidence")
|
||||
|
||||
prob_df = pd.DataFrame({
|
||||
'Outcome': ['Dropout', 'Enrolled', 'Graduate'],
|
||||
@@ -462,7 +517,7 @@ def main():
|
||||
with col_a:
|
||||
st.markdown(f"""
|
||||
<div class="metric-card">
|
||||
<h4>🎓 Graduate</h4>
|
||||
<h4>Graduate</h4>
|
||||
<h2>{prediction_proba[2]:.1%}</h2>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
@@ -470,7 +525,7 @@ def main():
|
||||
with col_b:
|
||||
st.markdown(f"""
|
||||
<div class="metric-card">
|
||||
<h4>⚠️ Dropout</h4>
|
||||
<h4>Dropout</h4>
|
||||
<h2>{prediction_proba[0]:.1%}</h2>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
@@ -478,16 +533,16 @@ def main():
|
||||
with col_c:
|
||||
st.markdown(f"""
|
||||
<div class="metric-card">
|
||||
<h4>📚 Enrolled</h4>
|
||||
<h4>Enrolled</h4>
|
||||
<h2>{prediction_proba[1]:.1%}</h2>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col2:
|
||||
st.markdown('<h2 class="sub-header">ℹ️ About the Model</h2>', unsafe_allow_html=True)
|
||||
st.markdown('<h2 class="sub-header">About the Model</h2>', unsafe_allow_html=True)
|
||||
|
||||
st.info("""
|
||||
**🤖 Model Details:**
|
||||
**Model Details:**
|
||||
- **Algorithm:** Random Forest Classifier
|
||||
- **Features:** 36 student characteristics
|
||||
- **Training Accuracy:** 100%
|
||||
@@ -495,7 +550,7 @@ def main():
|
||||
- **Classes:** Graduate, Dropout, Enrolled
|
||||
""")
|
||||
|
||||
st.markdown("### 📈 Key Factors")
|
||||
st.markdown("### Key Factors")
|
||||
st.markdown("""
|
||||
The model considers:
|
||||
- **Academic Performance** (grades, units)
|
||||
@@ -504,7 +559,7 @@ def main():
|
||||
- **Social Factors** (scholarships, special needs)
|
||||
""")
|
||||
|
||||
st.markdown("### 🎯 Use Cases")
|
||||
st.markdown("### Use Cases")
|
||||
st.markdown("""
|
||||
- **Early Warning System** for at-risk students
|
||||
- **Resource Allocation** planning
|
||||
@@ -513,7 +568,7 @@ def main():
|
||||
""")
|
||||
|
||||
# Model performance visualization
|
||||
st.markdown("### 📊 Model Performance")
|
||||
st.markdown("### Model Performance")
|
||||
|
||||
# Create a simple performance chart
|
||||
metrics = ['Accuracy', 'Precision', 'Recall', 'F1-Score']
|
||||
@@ -541,7 +596,7 @@ def main():
|
||||
|
||||
# Footer
|
||||
st.markdown("---")
|
||||
st.markdown("*Developed with ❤️ using Streamlit and scikit-learn*")
|
||||
st.markdown("*Developed using Streamlit and scikit-learn*")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user