import streamlit as st import pandas as pd import altair as alt from backend.db import Session def stats_ui(session: Session, grades_table: pd.DataFrame, grades: list): with st.expander('Statistiken'): number_students = len(session.points_df) number_participants = len(session.points_df[session.points_df['Punkte'].notna()]) if number_participants > 0: # Convert from categorical strings to numerical values points_table = session.points_df.reset_index()[['Punkte', 'Note']].copy().dropna() points_table['Note'] = points_table['Note'].apply(lambda x: float(f'{x}'.replace(',', '.'))) grades_tab = grades_table['Note'].apply(lambda x: float(f'{x}'.replace(',', '.'))) score_hist = pd.DataFrame({'Anzahl': [0] * len(grades_tab)}, index=grades_tab) counts = pd.DataFrame(points_table['Note'].value_counts().rename('Anzahl')) score_hist.update(counts) score_hist.reset_index(inplace=True) hist = alt.Chart(score_hist).mark_bar().encode( x=alt.X('Anzahl:Q', axis=alt.Axis(title='Anzahl', tickCount=score_hist['Anzahl'].max()+1, grid=True)), y=alt.Y('Note:O', bin=alt.Bin(binned=True), axis=alt.Axis(title='Note', grid=True)) ) median = alt.Chart(points_table).mark_rule(color='blue', opacity=0.5).encode( y = 'median(Note):O', size=alt.value(5), ) mean = alt.Chart(points_table).mark_rule(color='orange', opacity=0.5, strokeDash=[5,5]).encode( y = 'mean(Note):O', size=alt.value(5), ) chart = (hist + median + mean) st.altair_chart(chart, use_container_width=True) passed = 1-score_hist.iloc[-1]["Anzahl"]/number_participants 1-score_hist.iloc[-1]["Anzahl"]/number_participants left, mid, right, rightmost = st.columns(4) with left: st.write(f'Anzahl Anmeldungen: {number_students}') st.write(f'Anzahl Teilnehmer: {number_participants}') with mid: st.write(f'Bestanden: :green[{passed*100:.2f} %]') st.write(f'Durchgefallen: :red[{100-passed*100:.2f}%]') with right: st.write(f'Punkteuntergrenzen: :gray[(1,0)] {session.grade_1_0:.2f}% / :gray[(4,0)] {session.grade_4_0:.2f}%') st.write(f'Maximalpunktzahl: {session.max_points}') with rightmost: st.write(f':orange[Durchschnitt:] {points_table["Note"].mean():.2f}') st.write(f':blue[Median:] {points_table["Note"].median():.2f}') else: st.write(':orange[Keine Teilnehmer]')