File size: 5,925 Bytes
4d9b578
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# Import necessary libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import streamlit as st
from scipy.stats import ttest_ind
from scipy.stats import median_abs_deviation

# Load the gradebook data
gradebook = pd.read_csv('FAKE_EXAMPLE_DATA.csv')

# Define the assignment groups
assignment_groups = {
    "attendance": [column for column in gradebook.columns if 'Attendance' in column],  
    "study_activities": [column for column in gradebook.columns if 'Study' in column],  
    "quizzes": [column for column in gradebook.columns if 'Quiz' in column],  
    "midterms": [column for column in gradebook.columns if 'Midterm' in column],  
    "final_exam": [column for column in gradebook.columns if 'Final_Exam' in column]
}

# Add a title to the app
st.title("Minimizing Inequity in Grading")

# Create sidebar for weightings
weightings = {group: st.sidebar.slider(f'{group} weighting', min_value=0.000, max_value=1.000, value=0.2, step=0.01) for group in assignment_groups.keys()}

# Create sidebar for dropped scores
dropped_scores = {group: st.sidebar.slider(f'{group} dropped scores', min_value=0, max_value=6, value=0) for group in assignment_groups.keys()}

# Create sidebar for minimum scores
minimum_scores = {group: st.sidebar.slider(f'{group} minimum score', min_value=0.0, max_value=1.0, value=0.0, step=0.01) for group in assignment_groups.keys()}

# Define the function for calculating final grades
def calculate_final_grade(gradebook, assignment_groups, weightings, dropped_scores, minimum_scores):
    
    # Initialize a DataFrame to store the final grades
    final_grades = pd.DataFrame()
    final_grades["ID"] = gradebook["ID"]
    final_grades["demographic_group"] = gradebook["demographic_group"]

    # Initialize a Series to store the total weights (for normalization)
    total_weights = pd.Series(0, index=gradebook.index)

    # Loop over each assignment group
    for group, columns in assignment_groups.items():
        # Calculate the total score for the group, replacing missing or below-minimum scores with the minimum
        group_scores = gradebook[columns].apply(pd.to_numeric, errors='coerce')
        group_scores = group_scores.fillna(minimum_scores[group]).clip(lower=minimum_scores[group])

        # Drop the lowest scores
        if dropped_scores[group] > 0:
            group_scores = group_scores.apply(lambda row: row.nlargest(len(row) - dropped_scores[group]), axis=1)

        # Calculate the average score for the group
        group_averages = group_scores.mean(axis=1)

        # Multiply by the weight and add to the final grades
        final_grades[group] = group_averages * weightings[group]
        total_weights += weightings[group]

    # Normalize the final grades by the total weights
    final_grades["Final_Grade"] = final_grades.drop(columns=["ID", "demographic_group"]).sum(axis=1) / total_weights

    return final_grades

# Calculate final grades
final_grades = calculate_final_grade(gradebook, assignment_groups, weightings, dropped_scores, minimum_scores)

# Display the final grades
# st.write(final_grades.head())

# Calculate summary statistics for each group
summary_statistics = final_grades.groupby("demographic_group")["Final_Grade"].describe()

# Calculate the median for each group
demo1_median = final_grades[final_grades["demographic_group"] == True]["Final_Grade"].median()
non_demo1_median = final_grades[final_grades["demographic_group"] == False]["Final_Grade"].median()

# Calculate the difference between the medians
median_difference = demo1_median - non_demo1_median

# Convert to percentage and round to 2 decimal places
demo1_median = round(demo1_median * 100, 2)
non_demo1_median = round(non_demo1_median * 100, 2)
median_difference = round(median_difference * 100, 2)

# Display the medians
st.markdown(f"<p style='font-size:28px;'>This data is FAKE and only for the purpose of demonstrating the app.</p>", unsafe_allow_html=True)
st.markdown(f"<p style='font-size:20px;'>Demographic Group 1 Median Grade: {demo1_median}%</p>", unsafe_allow_html=True)
st.markdown(f"<p style='font-size:20px;'>Demographic Group 2 Median Grade: {non_demo1_median}%</p>", unsafe_allow_html=True)
st.markdown(f"<p style='font-size:20px;'>Median Difference: {median_difference}%</p>", unsafe_allow_html=True)

# Plot histograms of final grades for each group
plt.hist(final_grades.loc[final_grades["demographic_group"] == False, "Final_Grade"], bins=50, histtype='step', label='Demographic Group 2', color='blue')
plt.hist(final_grades.loc[final_grades["demographic_group"] == True, "Final_Grade"], bins=50, histtype='step', label='Demographic Group 1', color='orange')

# Add labels and legend
plt.xlabel('Final Grade')
plt.ylabel('Frequency')
plt.legend(loc='upper left')

# Display the plot
st.pyplot(plt)


# Calculate MAD for each group
demo1_mad = median_abs_deviation(final_grades.loc[final_grades["demographic_group"] == True, "Final_Grade"])
non_demo1_mad = median_abs_deviation(final_grades.loc[final_grades["demographic_group"] == False, "Final_Grade"])

st.write('Demographic Group 1 MAD: ', demo1_mad)
st.write('Demographic Group 2 MAD: ', non_demo1_mad)

# Display the summary statistics
st.write(summary_statistics)

# Conduct t-test
t_stat, p_value = ttest_ind(final_grades[final_grades["demographic_group"] == True]["Final_Grade"], 
                            final_grades[final_grades["demographic_group"] == False]["Final_Grade"], 
                            equal_var=False, nan_policy='omit')
st.write(f"P-value (t-test): {p_value}")

# Calculate Glass's Delta
non_demo1_std = final_grades.loc[final_grades["demographic_group"] == False, "Final_Grade"].std()
glass_delta = (final_grades.loc[final_grades["demographic_group"] == True, "Final_Grade"].mean() - final_grades.loc[final_grades["demographic_group"] == False, "Final_Grade"].mean()) / non_demo1_std
st.write('Glass Delta: ', glass_delta)