Initialer Commit: curriculare Analyse NFS-H

This commit is contained in:
2025-05-31 07:58:20 +02:00
commit 7b5f6eb6bf
6 changed files with 552 additions and 0 deletions

80
.gitignore vendored Normal file
View File

@ -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

View File

@ -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
1 Kürzel Kompetenzbereich
2 1a fachlich
3 1b fachlich
4 1c fachlich
5 1d fachlich
6 1e fachlich
7 1f fachlich
8 2a fachlich
9 2b fachlich
10 2c fachlich
11 2d methodisch
12 2e methodisch
13 2f methodisch
14 2g methodisch
15 2h methodisch
16 3a sozial
17 3b sozial
18 3c sozial
19 3d sozial
20 3e sozial
21 4a methodisch
22 4b methodisch
23 4c methodisch
24 5a methodisch
25 5b methodisch
26 5c methodisch
27 5d methodisch
28 5e methodisch
29 6a methodisch
30 6b methodisch
31 6c methodisch
32 6d methodisch
33 7a fachlich
34 7b fachlich
35 7c fachlich
36 7d fachlich
37 7e fachlich
38 7f fachlich
39 7g fachlich
40 7h fachlich
41 7i fachlich
42 8a personal
43 8b personal
44 8c personal
45 8d personal
46 9a personal
47 9b personal
48 9c personal
49 9d personal
50 9e personal
51 10a sozial
52 10b sozial
53 10c sozial
54 10d sozial

32
README.md Normal file
View File

@ -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.

5
config_lms.py Normal file
View File

@ -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

BIN
lms-verteilung.xlsx Normal file

Binary file not shown.

381
lms_statistische-analyse.py Normal file
View File

@ -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)