commit 7b5f6eb6bfa3b35e2d62d2041a9f07f917094ab2 Author: Jochen Hanisch-Johannsen Date: Sat May 31 07:58:20 2025 +0200 Initialer Commit: curriculare Analyse NFS-H diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f64f4f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,80 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ + +# Pytest +.pytest_cache/ + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre +.pyre/ + +# profiling +prof/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# pipenv +Pipfile.lock + +# pyright +.pyright/ + +# vscode +.vscode/ + +# system files +.DS_Store + +# Output files +# Ignore only generated or temporary figures in Abbildungen/ +Abbildungen/*.tmp.* +Abbildungen/*_entwurf.* +*.html +*.png diff --git a/APrV-Kuerzel_zu_Kompetenzbereichen.csv b/APrV-Kuerzel_zu_Kompetenzbereichen.csv new file mode 100644 index 0000000..9acbd7f --- /dev/null +++ b/APrV-Kuerzel_zu_Kompetenzbereichen.csv @@ -0,0 +1,54 @@ +Kürzel,Kompetenzbereich +1a,fachlich +1b,fachlich +1c,fachlich +1d,fachlich +1e,fachlich +1f,fachlich +2a,fachlich +2b,fachlich +2c,fachlich +2d,methodisch +2e,methodisch +2f,methodisch +2g,methodisch +2h,methodisch +3a,sozial +3b,sozial +3c,sozial +3d,sozial +3e,sozial +4a,methodisch +4b,methodisch +4c,methodisch +5a,methodisch +5b,methodisch +5c,methodisch +5d,methodisch +5e,methodisch +6a,methodisch +6b,methodisch +6c,methodisch +6d,methodisch +7a,fachlich +7b,fachlich +7c,fachlich +7d,fachlich +7e,fachlich +7f,fachlich +7g,fachlich +7h,fachlich +7i,fachlich +8a,personal +8b,personal +8c,personal +8d,personal +9a,personal +9b,personal +9c,personal +9d,personal +9e,personal +10a,sozial +10b,sozial +10c,sozial +10d,sozial diff --git a/README.md b/README.md new file mode 100644 index 0000000..d3b487f --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +# Learning Management System – Curriculum Analyse + +Dieses Projekt enthält die vollständige Python-gestützte Analyse der curricularen Struktur des digitalen Bildungsraums „NFS-H“. Ziel ist die datenbasierte Validierung der curricularen Kohärenz anhand der Ausbildungs- und Prüfungsverordnung für Notfallsanitäter*innen (NotSan-APrV). + +## Zielsetzung + +Nachgewiesen werden: +- curriculare Konsistenz (Korrelation Aufgaben vs. Dauer, r = 0.66) +- inhaltliche Validität (Deckung mit APrV-Themenverteilung: 47/27/26) +- strukturierte Kompetenzorientierung (fachlich, sozial, personal, methodisch) +- Visualisierungen zur quantitativen Analyse + +## Inhalt + +- `lms_statistische-analyse.py`: Hauptskript zur statistischen Auswertung +- `lms-verteilung.xlsx`: Zuordnung von Handlungssituationen zu APrV-Kürzeln +- `APrV-Kuerzel_zu_Kompetenzbereichen.csv`: Mapping von Kürzeln zu Kompetenzbereichen +- Visualisierungen werden automatisiert erzeugt; exportierte PNG-Dateien sind optional und werden lokal gespeichert + +## Methoden + +- Automatisierte Zuordnung über Pandas +- Visualisierung mit Plotly (Boxplots, Tortendiagramme, Balkendiagramme) +- Vergleich mit APrV-Gesetzesvorgaben als Referenzstruktur + +## Lizenz + +MIT License – siehe `LICENSE` + +## Hinweis + +Dieses Repository ist Bestandteil der Dissertationsarbeit an der Charité – Universitätsmedizin Berlin. \ No newline at end of file diff --git a/config_lms.py b/config_lms.py new file mode 100644 index 0000000..ae21bbe --- /dev/null +++ b/config_lms.py @@ -0,0 +1,5 @@ + +# Visualisierungs- und Darstellungsparameter für Plotly-Diagramme +plotly_theme = "dark" # CI-konformes Plotly-Theme: "dark" oder "light" +export_fig_visual = False # Steuerung, ob Visualisierungen exportiert werden +export_fig_png = False # Separater Schalter für PNG-Export diff --git a/lms-verteilung.xlsx b/lms-verteilung.xlsx new file mode 100644 index 0000000..9ba8069 Binary files /dev/null and b/lms-verteilung.xlsx differ diff --git a/lms_statistische-analyse.py b/lms_statistische-analyse.py new file mode 100644 index 0000000..bc3c1b1 --- /dev/null +++ b/lms_statistische-analyse.py @@ -0,0 +1,381 @@ +import pandas as pd +import plotly.graph_objs as go +import os +import re +import unicodedata +import subprocess +from config_lms import plotly_theme, export_fig_visual, export_fig_png +import sys +sys.path.append("/Users/jochen_hanisch-johannsen/Documents/scripte/Jochen-Hanisch/CI/ci_template") +from plotly_template import get_standard_layout, get_colors, set_theme +from pathlib import Path +set_theme(plotly_theme) + +# --- Hilfsfunktionen für Export und Slugify --- +def slugify(text): + text = unicodedata.normalize('NFKD', text) + text = text.encode('ascii', 'ignore').decode('ascii') + text = re.sub(r'[^\w\s-]', '', text) + text = re.sub(r'[\s]+', '-', text) + return text.strip().lower() + +def export_figure(fig, name, export_flag_html, export_flag_png): + filename_part = "notsan-aprv-vergleich" + safe_filename = slugify(f"{name}_{filename_part}") + remote_path = "jochen-hanisch@sternenflottenakademie.local:/mnt/deep-space-nine/public/plot/promotion/" + + if export_flag_html: + export_path_html = os.path.join("..", "Allgemein beruflich", "Research", "Forschungsprojekte", "Systemische Kompetenzentwicklung für High Responsibility Teams", f"{safe_filename}.html") + fig.write_html(export_path_html, full_html=True, include_plotlyjs="cdn") + try: + subprocess.run(["scp", export_path_html, remote_path], check=True) + print(f"✅ HTML-Datei '{export_path_html}' erfolgreich übertragen.") + os.remove(export_path_html) + print(f"🗑️ Lokale HTML-Datei '{export_path_html}' wurde gelöscht.") + except subprocess.CalledProcessError as e: + print("❌ Fehler beim HTML-Übertragen:") + print(e.stderr) + + if export_flag_png: + export_path_png = os.path.join("..", "Allgemein beruflich", "Research", "Forschungsprojekte", "Systemische Kompetenzentwicklung für High Responsibility Teams", f"{safe_filename}.png") + try: + fig.write_image(export_path_png, width=1200, height=800, scale=2) + print(f"✅ PNG-Datei lokal gespeichert: '{export_path_png}'") + except Exception as e: + print("❌ Fehler beim PNG-Export:", str(e)) + +# PNG-Exportpfad definieren +png_export_path = Path(__file__).parent.parent.parent / "Allgemein beruflich" / "Research" / "Charité - Universitätsmedizin Berlin" / "Dissertation" / "Abbildungen" + +# Ursprüngliche Datentabelle (bitte bei Bedarf anpassen) +df = pd.DataFrame({ + "Kursbezeichnung": [ + "NFS-H-01", "NFS-H-02", "NFS-H-03", "NFS-H-04", "NFS-H-05", "NFS-H-06", + "NFS-H-07", "NFS-H-08", "NFS-H-09", "NFS-H-10", "NFS-H-11", "NFS-H-12", + "NFS-H-13", "NFS-H-14", "NFS-H-15", "NFS-H-16", "NFS-H-17", "NFS-H-18", + "NFS-H-19", "NFS-H-20", "NFS-H-21", "NFS-H-22", "NFS-H-23", "NFS-H-24", + "NFS-H-25", "NFS-H-26", "NFS-H-27", "NFS-H-28", "NFS-H-29", "NFS-H-30", + "NFS-H-31", "NFS-H-32" + ], + "Titel": [ + "Einführung in die berufliche Ausbildung", "Das eigene Berufsfeld erkunden und berufliches Selbstverständnis entwickeln", + "Die eigene Lehrrettungswache erleben", "Das rettungsdienstliche Umfeld kennen lernen", "Mit sich selbst und Anderen umgehen", + "Einen Patienten im Krankentransport beurteilen", "Lebensrettende Maßnahmen durchführen", "Eine Einsatzfahrt durchführen", + "Einen Krankentransport durchführen", "Mit BOS-Peers kommunizieren", "Mit unterschiedlichen Patienten-Peers kommunizieren", + "Beratungsgespräche führen", "Mit Sterben im Rettungsdienst umgehen", "Einen Einsatz in der primären Notfallmedizin durchführen", + "Einen Notfallpatienten beurteilen", "Patienten mit A-Problem behandeln", "Patienten mit B-Problem behandeln", + "Patienten mit C-Problem behandeln", "Patienten mit D-Problem behandeln", "Patienten mit E-Problem behandeln", + "Einen pädiatrischen Patienten behandeln", "Einen Einsatz in der Sekundärrettung durchführen", + "Urologische und nephrologische Notfälle versorgen", "Hals-Nasen-Ohren Erkrankungen und Verletzungen versorgen", + "Mit psychischen Erkrankungen und Notfällen umgehen", "Eine gynäkologische Patientin versorgen", + "Notfälle der Wasserrettung versorgen", "Einsätze mit besonderen Verhaltensmaßnahmen durchführen", + "Einsätze mit besonderer Logistik durchführen", "Mit BOS zusammenarbeiten", "Das eigene Berufsfeld reflektieren", + "Vorbereitung auf die Notfallsanitäterprüfung" + ], + "∑ Aufgaben": [ + 6, 16, 28, 37, 31, 14, 47, 36, 11, 25, 12, 18, 15, 18, 24, 26, 24, 36, 20, 57, 15, 11, 17, 19, 11, 22, 9, 61, 55, 13, 54, 60 + ], + "Dauer [d]": [ + 7, 32, 17, 31, 53, 15, 67, 77, 13, 42, 2, 7, 4, 20, 31, 48, 7, 12, 29, 90, 2, 53, 5, 2, 42, 18, 2, 93, 100, 5, 5, 40 + ] +}) + +# --- Automatische Berechnung Themenbereichsanteile pro Kurs --- +# Ausschließlich systematische APrV-Zuordnung aus lms-verteilung.xlsx und zuordnung_praezise verwenden +from collections import defaultdict + +zuordnung_praezise = { + # Medizinisch + "1a": "medizinisch", "1b": "medizinisch", "1c": "medizinisch", "1d": "rettungsdienstlich", "1e": "medizinisch", "1f": "medizinisch", + "7a": "medizinisch", "7b": "medizinisch", "7c": "medizinisch", "7d": "medizinisch", + "7e": "medizinisch", "7f": "medizinisch", "7g": "medizinisch", "7h": "medizinisch", "7i": "medizinisch", + # Rettungsdienstlich + "2a": "rettungsdienstlich", "2b": "rettungsdienstlich", "2c": "rettungsdienstlich", "2d": "rettungsdienstlich", "2e": "rettungsdienstlich", "2f": "rettungsdienstlich", "2g": "rettungsdienstlich", "2h": "rettungsdienstlich", + "4a": "rettungsdienstlich", "4b": "rettungsdienstlich", "4c": "rettungsdienstlich", + "5a": "rettungsdienstlich", "5b": "rettungsdienstlich", "5c": "rettungsdienstlich", "5d": "rettungsdienstlich", "5e": "rettungsdienstlich", + # Bezugswissenschaftlich + "3a": "bezugswissenschaftlich", "3b": "bezugswissenschaftlich", "3c": "bezugswissenschaftlich", "3d": "bezugswissenschaftlich", "3e": "bezugswissenschaftlich", + "6a": "bezugswissenschaftlich", "6b": "bezugswissenschaftlich", "6c": "bezugswissenschaftlich", "6d": "bezugswissenschaftlich", + "8a": "bezugswissenschaftlich", "8b": "bezugswissenschaftlich", "8c": "bezugswissenschaftlich", "8d": "bezugswissenschaftlich", + "9a": "bezugswissenschaftlich", "9b": "bezugswissenschaftlich", "9c": "bezugswissenschaftlich", "9d": "bezugswissenschaftlich", "9e": "bezugswissenschaftlich", + "10a": "bezugswissenschaftlich", "10b": "bezugswissenschaftlich", "10c": "bezugswissenschaftlich", "10d": "bezugswissenschaftlich" +} + +# Systematische Zuordnung aus externer Excel +df_para = pd.read_excel(Path(__file__).parent / "lms-verteilung.xlsx") +df_para = df_para.set_index("Nummer") + +anteile_liste = [] +for idx, row in df.iterrows(): + kursnummer = int(row["Kursbezeichnung"].split("-")[-1]) + if kursnummer not in df_para.index: + # Keine manuelle Kurs-Zuordnung mehr, ausschließlich systematische APrV-Zuordnung + d = "unbekannt" + print(f"❗ Kurs {kursnummer} ({row['Titel']}) hat unbekannten Themenbereich.") + print(f" → Verwendete APrV-Kürzel: {[ ]}") + anteile_liste.append((0, 0, 0, "unbekannt")) + continue + else: + para_raw = df_para.loc[kursnummer, "NotSan-APrV"] + if pd.isna(para_raw): + d = "unbekannt" + print(f"❗ Kurs {kursnummer} ({row['Titel']}) hat unbekannten Themenbereich.") + print(f" → Verwendete APrV-Kürzel: {[ ]}") + anteile_liste.append((0, 0, 0, "unbekannt")) + continue + else: + para_liste = [p.strip() for p in str(para_raw).split(",")] + zähler = defaultdict(int) + gesamt = 0 + for para in para_liste: + bereich = zuordnung_praezise.get(para) + if bereich: + zähler[bereich] += 1 + gesamt += 1 + m = round(zähler["medizinisch"] / gesamt * 100, 2) if gesamt else 0 + r = round(zähler["rettungsdienstlich"] / gesamt * 100, 2) if gesamt else 0 + b = round(zähler["bezugswissenschaftlich"] / gesamt * 100, 2) if gesamt else 0 + d = max(("medizinisch", m), ("rettungsdienstlich", r), ("bezugswissenschaftlich", b), key=lambda x: x[1])[0] if gesamt else "unbekannt" + # Debug-Ausgabe bei unbekanntem Themenbereich + if d == "unbekannt": + print(f"❗ Kurs {kursnummer} ({row['Titel']}) hat unbekannten Themenbereich.") + print(f" → Verwendete APrV-Kürzel: {para_liste}") + anteile_liste.append((m, r, b, d)) + +df["Anteil medizinisch"], df["Anteil rettungsdienstlich"], df["Anteil bezugswissenschaftlich"], df["Themenbereich"] = zip(*anteile_liste) + +# +# --- APrV-Grundlagen: Themenschwerpunkte und Kompetenzbereiche --- +# +# Grundlage: APrV-Zuordnung durch Schüler*innen (prozentuale Verteilung nach Stunden) +# Thematische Gewichtung nach APrV +apr_theme_df = pd.DataFrame({ + "Thema": ["medizinisch", "rettungsdienstlich", "bezugswissenschaftlich"], + "Stunden": [496, 909, 515], + "Anteil (%)": [27, 47, 26] +}) + +# Kompetenzgewichtung nach APrV +apr_kompetenz_df = pd.DataFrame({ + "Kompetenz": ["fachlich", "sozial", "personal", "methodisch"], + "Stunden": [464, 294, 206, 956], + "Anteil (%)": [24, 15, 11, 50] +}) + + + + + +# Umbenennung "unbekannt" → "Einführung/Prüfung" für valide Kategorisierung +df["Themenbereich"] = df["Themenbereich"].replace("unbekannt", "Einführung/Prüfung") + +# Deskriptive Gesamtstatistik +gesamt_stats = { + "Anzahl Kurse": len(df), + "Gesamtaufgaben": df["∑ Aufgaben"].sum(), + "Gesamtdauer [d]": df["Dauer [d]"].sum(), + "Ø Aufgaben pro Kurs": df["∑ Aufgaben"].mean(), + "Ø Dauer pro Kurs [d]": df["Dauer [d]"].mean(), + "Median Aufgaben": df["∑ Aufgaben"].median(), + "Median Dauer [d]": df["Dauer [d]"].median(), + "Standardabweichung Aufgaben": df["∑ Aufgaben"].std(), + "Standardabweichung Dauer [d]": df["Dauer [d]"].std(), + "Min Aufgaben": df["∑ Aufgaben"].min(), + "Max Aufgaben": df["∑ Aufgaben"].max(), + "Min Dauer [d]": df["Dauer [d]"].min(), + "Max Dauer [d]": df["Dauer [d]"].max(), + "Korrelation Aufgaben vs. Dauer": df["∑ Aufgaben"].corr(df["Dauer [d]"]) +} +print("Gesamtstatistik:\n", pd.Series(gesamt_stats).round(2)) + +# Gruppierte Statistik +gruppe = df.groupby("Themenbereich").agg({ + "∑ Aufgaben": ["mean", "std", "count"], + "Dauer [d]": ["mean", "std"] +}).round(2) +gruppe.columns = ['Ø Aufgaben', 'SD Aufgaben', 'Anzahl Kurse', 'Ø Dauer', 'SD Dauer'] +print("\nStatistik nach Themenbereich:\n", gruppe) + + +def plot_boxplots(df): + colors = get_colors() + # Spezifische Reihenfolge: medizinisch, rettungsdienstlich, bezugswissenschaftlich, Einführung/Prüfung + kategorie_order = [] + for k in ["medizinisch", "rettungsdienstlich", "bezugswissenschaftlich", "Einführung/Prüfung"]: + if k in df["Themenbereich"].unique(): + kategorie_order.append(k) + # Ergänze ggf. andere Kategorien (falls weitere vorkommen) + for k in sorted(df["Themenbereich"].unique()): + if k not in kategorie_order: + kategorie_order.append(k) + + # Aufgaben-Boxplot + fig1 = go.Figure() + for k in kategorie_order: + d = df[df["Themenbereich"] == k] + fig1.add_trace(go.Box( + y=d["∑ Aufgaben"], + name=k, + boxmean='sd', + marker=dict(color=colors["secondaryLine"]), + line=dict(color=colors["primaryLine"]) + )) + fig1.update_layout(get_standard_layout( + title="Verteilung der Aufgaben pro Themenbereich", + x_title="Themenbereich", + y_title="∑ Aufgaben" + )) + export_figure(fig1, fig1.layout.title.text, export_fig_visual, export_fig_png) + fig1.show() + + # Dauer-Boxplot + fig2 = go.Figure() + for k in kategorie_order: + d = df[df["Themenbereich"] == k] + fig2.add_trace(go.Box( + y=d["Dauer [d]"], + name=k, + boxmean='sd', + marker=dict(color=colors["secondaryLine"]), + line=dict(color=colors["primaryLine"]) + )) + fig2.update_layout(get_standard_layout( + title="Verteilung der Kursdauer pro Themenbereich", + x_title="Themenbereich", + y_title="Dauer in Tagen" + )) + export_figure(fig2, fig2.layout.title.text, export_fig_visual, export_fig_png) + fig2.show() + + +def plot_aprv_pies(): + colors = get_colors() + + # Thema-Tortendiagramm + fig1 = go.Figure(data=[go.Pie( + labels=apr_theme_df["Thema"], + values=apr_theme_df["Anteil (%)"], + marker=dict(colors=[colors["primaryLine"], colors["secondaryLine"], colors["depthArea"]]), + textinfo='label+percent', + insidetextorientation='radial' + )]) + fig1.update_layout(get_standard_layout( + title="Anteil der Themenbereiche nach APrV", + x_title="", y_title="" + )) + fig1.update_layout(showlegend=True) + export_figure(fig1, fig1.layout.title.text, export_fig_visual, export_fig_png) + fig1.show() + + # Kompetenz-Tortendiagramm + fig2 = go.Figure(data=[go.Pie( + labels=apr_kompetenz_df["Kompetenz"], + values=apr_kompetenz_df["Anteil (%)"], + marker=dict(colors=[ + colors["primaryLine"], colors["secondaryLine"], + colors["depthArea"], colors["brightArea"] + ]), + textinfo='label+percent', + insidetextorientation='radial' + )]) + fig2.update_layout(get_standard_layout( + title="Anteil der Kompetenzbereiche nach APrV", + x_title="", y_title="" + )) + fig2.update_layout(showlegend=True) + export_figure(fig2, fig2.layout.title.text, export_fig_visual, export_fig_png) + fig2.show() + + +def plot_vergleich_lehrplan_aprv(): + # Gruppierung der Kursdauer nach Themenbereich + nfsh_theme = df.groupby("Themenbereich")["Dauer [d]"].sum().reset_index() + nfsh_theme["Anteil (%)"] = 100 * nfsh_theme["Dauer [d]"] / nfsh_theme["Dauer [d]"].sum() + + # Zusammenführung mit Schüler*innen-Schätzung aus APrV + vergleich_df = pd.merge( + apr_theme_df[["Thema", "Anteil (%)"]].rename(columns={"Anteil (%)": "Schätzung APrV"}), + nfsh_theme.rename(columns={"Themenbereich": "Thema", "Anteil (%)": "NFS-H-Anteil"}), + on="Thema" + ) + + # Visualisierung: Gegenüberstellung als Balkendiagramm + colors = get_colors() + fig = go.Figure(data=[ + go.Bar(name='Schätzung APrV', x=vergleich_df["Thema"], y=vergleich_df["Schätzung APrV"], + marker_color=colors["primaryLine"]), + go.Bar(name='NFS-H-Anteil', x=vergleich_df["Thema"], y=vergleich_df["NFS-H-Anteil"], + marker_color=colors["secondaryLine"]) + ]) + fig.update_layout( + get_standard_layout("Vergleich Themengewichtung: APrV-Schätzung vs. NFS-H-Lehrplan", "Thema", "Anteil [%]"), + barmode='group' + ) + export_figure(fig, fig.layout.title.text, export_fig_visual, export_fig_png) + fig.show() + + + + +def plot_vergleich_kompetenz_aprv(): + # Automatische Zuordnung der Kompetenzbereiche basierend auf CSV-Datei + kuerzel_df = pd.read_csv(Path(__file__).parent / "APrV-Kuerzel_zu_Kompetenzbereichen.csv") + kuerzel_map = dict(zip(kuerzel_df["Kürzel"], kuerzel_df["Kompetenzbereich"])) + + kompetenz_liste = [] + for idx, row in df.iterrows(): + kursnummer = int(row["Kursbezeichnung"].split("-")[-1]) + if kursnummer not in df_para.index: + kompetenz_liste.append("unbekannt") + continue + para_raw = df_para.loc[kursnummer, "NotSan-APrV"] + if pd.isna(para_raw): + kompetenz_liste.append("unbekannt") + continue + para_liste = [p.strip() for p in str(para_raw).split(",")] + zähler = defaultdict(int) + for para in para_liste: + komp = kuerzel_map.get(para) + if komp: + zähler[komp] += 1 + if zähler: + hauptkategorie = max(zähler.items(), key=lambda x: x[1])[0] + else: + hauptkategorie = "unbekannt" + kompetenz_liste.append(hauptkategorie) + + df["Kompetenzbereich"] = kompetenz_liste + + # Gruppierung nach Kompetenzbereich + nfsh_k = df.groupby("Kompetenzbereich")["Dauer [d]"].sum().reset_index() + nfsh_k["Anteil (%)"] = 100 * nfsh_k["Dauer [d]"] / nfsh_k["Dauer [d]"].sum() + + # Merge mit APrV-Kompetenzverteilung + vergleich_k = pd.merge( + apr_kompetenz_df[["Kompetenz", "Anteil (%)"]].rename(columns={"Anteil (%)": "Schätzung APrV"}), + nfsh_k.rename(columns={"Kompetenzbereich": "Kompetenz", "Anteil (%)": "NFS-H-Anteil"}), + on="Kompetenz" + ) + + # Visualisierung + colors = get_colors() + fig = go.Figure(data=[ + go.Bar(name='Schätzung APrV', x=vergleich_k["Kompetenz"], y=vergleich_k["Schätzung APrV"], + marker_color=colors["primaryLine"]), + go.Bar(name='NFS-H-Anteil', x=vergleich_k["Kompetenz"], y=vergleich_k["NFS-H-Anteil"], + marker_color=colors["secondaryLine"]) + ]) + fig.update_layout( + get_standard_layout("Vergleich Kompetenzgewichtung: APrV-Schätzung vs. NFS-H-Lehrplan", "Kompetenzbereich", "Anteil [%]"), + barmode='group' + ) + export_figure(fig, fig.layout.title.text, export_fig_visual, export_fig_png) + fig.show() + + +# --- Visualisierungen aufrufen --- +# Alle Visualisierungen in sinnvoller Reihenfolge aufrufen +plot_aprv_pies() +plot_vergleich_lehrplan_aprv() +plot_vergleich_kompetenz_aprv() +plot_boxplots(df)