Initial commit

This commit is contained in:
Jonas Karneboge 2026-09-22 18:35:43 +02:00
commit 3cba772836
1341 changed files with 532924 additions and 0 deletions

BIN
FLZ/.RData Normal file

Binary file not shown.

1
FLZ/.Rprofile Normal file
View file

@ -0,0 +1 @@
source("renv/activate.R")

13
FLZ/FLZ.Rproj Normal file
View file

@ -0,0 +1,13 @@
Version: 1.0
RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default
EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8
RnwWeave: Sweave
LaTeX: pdfLaTeX

904
FLZ/app.R Normal file
View file

@ -0,0 +1,904 @@
# Präambel ####
library(shiny)
library(dplyr)
library(ggplot2)
library(haven)
library(officer)
library(DBI)
library(RSQLite)
PFAD_DOWNLOAD_SKRIPT = "../API/get_data_flz.R" # liefert: daten_flz
PFAD_PSEUDONYM_SKRIPT = "../get_pseudo.R" # liefert: pseudo
PFAD_NORMTABELLE = "normtabellen_flz.csv" # liegt im App-Verzeichnis, liefert die Normdaten
AKZENT_FARBE = "#8B2635"
APP_VERZEICHNIS = normalizePath(getwd())
absPath = function(pfad) {
if (grepl("^([A-Za-z]:[/\\\\]|/)", pfad)) return(pfad)
file.path(APP_VERZEICHNIS, pfad)
}
PFAD_DOWNLOAD_SKRIPT = normalizePath(absPath(PFAD_DOWNLOAD_SKRIPT), mustWork = FALSE)
PFAD_PSEUDONYM_SKRIPT = normalizePath(absPath(PFAD_PSEUDONYM_SKRIPT), mustWork = FALSE)
FLZ_DISCLAIMER = paste0(
"Diese Auswertung ist ein Hilfsmittel fuer klinisches Fachpersonal und ersetzt ",
"keine fachliche Interpretation. Das Rohprofil ist fuer die Unterlagen der ",
"behandelnden Person gedacht und nicht zur unkommentierten Weitergabe an die ",
"betroffene Person bestimmt."
)
# Infrastruktur ####
app_css = "
.input-panel {
display: flex;
align-items: flex-end;
gap: 12px;
flex-wrap: wrap;
padding: 16px 20px;
margin-bottom: 16px;
background: #f5f5f5;
border-radius: 6px;
}
.btn-laden {
background-color: #8B2635;
border-color: #8B2635;
color: #fff;
}
.btn-laden:hover, .btn-laden:focus {
background-color: #6f1e2a;
border-color: #6f1e2a;
color: #fff;
}
.abschnitt-karte {
background: #fff;
padding: 16px 20px;
margin-bottom: 18px;
border: 1px solid #ddd;
border-radius: 6px;
}
.abschnitt-titel {
font-size: 1.15em;
font-weight: 700;
color: #8B2635;
border-bottom: 2px solid #8B2635;
padding-bottom: 8px;
margin-bottom: 14px;
}
.alert-fehler {
padding: 12px 16px;
margin-bottom: 14px;
background: #f8d7da;
border-left: 5px solid #C62828;
border-radius: 4px;
color: #58151c;
font-weight: 500;
}
.alert-warnung {
padding: 10px 16px;
margin-bottom: 12px;
background: #fff3cd;
border-left: 5px solid #E65100;
border-radius: 4px;
color: #6b5100;
font-size: 0.93em;
font-weight: 500;
}
.item-zeile {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 4px 0;
border-bottom: 1px solid #eee;
}
.item-nr {
font-weight: 600;
color: #8B2635;
min-width: 26px;
flex-shrink: 0;
}
.item-text {
flex: 1;
color: #333;
font-size: 0.92em;
}
.profil-zeile {
display: flex;
align-items: center;
gap: 10px;
padding: 6px 0;
border-bottom: 1px solid #f0f0f0;
}
.stanine-badge {
display: inline-block;
border-radius: 12px;
padding: 2px 10px;
font-size: 0.85em;
font-weight: 600;
white-space: nowrap;
}
.stanine-badge-unauffaellig {
background: #E8F5E9;
color: #2E7D32;
border: 1px solid #A5D6A7;
}
.stanine-badge-auffaellig {
background: #f0f0f0;
color: #555555;
border: 1px solid #cccccc;
}
"
app_css = gsub("#8B2635", AKZENT_FARBE, app_css, fixed = TRUE)
# Helper ####
FLZ_DOMAENEN = c("GES", "ARB", "FIN", "FRE", "EHE", "KIN", "PER", "SEX", "BEK", "WOH")
FLZ_SUM_DOMAENEN = c("GES", "FIN", "FRE", "PER", "SEX", "BEK", "WOH")
FLZ_OPTIONALE_DOMAENEN = c("ARB", "EHE", "KIN")
FLZ_DOMAENEN_NAMEN = c(
GES = "Gesundheit",
ARB = "Arbeit und Beruf",
FIN = "Finanzielle Lage",
FRE = "Freizeit",
EHE = "Ehe/Partnerschaft",
KIN = "Beziehung zu eigenen Kindern",
PER = "Eigene Person",
SEX = "Sexualität",
BEK = "Freunde, Bekannte, Verwandte",
WOH = "Wohnung"
)
FLZ_GRUPPEN = c(
"Gesamtstichprobe N=2870",
"Männer 14-25", "Männer 26-35", "Männer 36-45", "Männer 46-55",
"Männer 56-65", "Männer 66-75", "Männer über 75",
"Frauen 14-25", "Frauen 26-35", "Frauen 36-45", "Frauen 46-55",
"Frauen 56-65", "Frauen 66-75", "Frauen über 75"
)
extrahiere_stufe = function(x) {
# x kann character (Text der Choice) oder haven_labelled (dbl+lbl) sein
if (inherits(x, "haven_labelled")) {
x_chr = as.character(haven::as_factor(x))
} else {
x_chr = as.character(x)
}
as.numeric(sub("^\\s*([0-9]+).*$", "\\1", x_chr))
}
extrahiere_klartext = function(x) {
if (is.null(x) || length(x) == 0) return(NA_character_)
if (inherits(x, "haven_labelled")) {
return(trimws(as.character(haven::as_factor(x))))
}
trimws(as.character(x))
}
berechne_flz_scores = function(item_werte) {
domaenen_werte = list()
gesamt_fehlend = 0
for (dom in FLZ_DOMAENEN) {
item_namen = paste0("flz_", tolower(dom), "_", 1:7)
werte = as.numeric(item_werte[item_namen])
n_fehlend = sum(is.na(werte))
gesamt_fehlend = gesamt_fehlend + n_fehlend
if (n_fehlend == 0) {
domaenen_werte[[dom]] = sum(werte)
} else if (n_fehlend == 1) {
domaenen_werte[[dom]] = round(mean(werte, na.rm = TRUE) * 7)
} else {
domaenen_werte[[dom]] = NA_real_
}
}
ueberschreitung = gesamt_fehlend > 7
if (ueberschreitung) {
for (dom in FLZ_DOMAENEN) domaenen_werte[[dom]] = NA_real_
sum_wert = NA_real_
} else {
sum_domaenen_werte = unlist(domaenen_werte[FLZ_SUM_DOMAENEN])
if (any(is.na(sum_domaenen_werte))) {
sum_wert = NA_real_
} else {
sum_wert = sum(sum_domaenen_werte)
}
}
list(
domaenen = domaenen_werte,
sum = sum_wert,
n_fehlend_gesamt = gesamt_fehlend,
ueberschreitung = ueberschreitung
)
}
bestimme_gruppe = function(geschlecht, alter) {
geschlecht = trimws(geschlecht)
if (identical(geschlecht, "männlich")) {
praefix = "Männer"
} else if (identical(geschlecht, "weiblich")) {
praefix = "Frauen"
} else {
return(list(ok = FALSE, gruppe = NA_character_, warnung = sprintf(
"Geschlecht ('%s') konnte nicht eindeutig 'männlich' oder 'weiblich' zugeordnet werden. Keine geschlechtsspezifische Normgruppe verfügbar.",
ifelse(is.na(geschlecht) || geschlecht == "", "k. A.", geschlecht)
)))
}
alter_num = suppressWarnings(as.numeric(alter))
if (is.na(alter_num) || alter_num < 14) {
return(list(ok = FALSE, gruppe = NA_character_, warnung =
"Alter außerhalb der Normstichprobe / nicht auswertbar. Es wird nur die Gesamtstichprobe als Referenz angeboten."
))
}
alter_label =
if (alter_num <= 25) "14-25"
else if (alter_num <= 35) "26-35"
else if (alter_num <= 45) "36-45"
else if (alter_num <= 55) "46-55"
else if (alter_num <= 65) "56-65"
else if (alter_num <= 75) "66-75"
else "über 75"
list(ok = TRUE, gruppe = paste(praefix, alter_label), warnung = NULL)
}
bestimme_stanine = function(rohwert, normtabelle, gruppe, spalte) {
if (is.na(rohwert)) {
return(list(stanine = NA_integer_, status = "nicht_berechenbar"))
}
zeilen = normtabelle[normtabelle$gruppe == gruppe, ]
zeilen = zeilen[order(zeilen$stanine), ]
for (i in seq_len(nrow(zeilen))) {
zellwert = trimws(zeilen[[spalte]][i])
if (identical(zellwert, "-") || nchar(zellwert) == 0) next
grenzen = suppressWarnings(as.numeric(strsplit(zellwert, "-")[[1]]))
if (length(grenzen) != 2 || any(is.na(grenzen))) next
if (rohwert >= grenzen[1] && rohwert <= grenzen[2]) {
return(list(stanine = as.integer(sub("ST", "", zeilen$stanine[i])), status = "ok"))
}
}
list(stanine = NA_integer_, status = "ausserhalb_normstichprobe")
}
stanine_badge_klasse = function(stanine) {
if (is.na(stanine)) return("")
if (stanine >= 4 && stanine <= 6) "stanine-badge-unauffaellig" else "stanine-badge-auffaellig"
}
FLZ_STUFEN_TEXT = c(
"1" = "sehr unzufrieden",
"2" = "unzufrieden",
"3" = "eher unzufrieden",
"4" = "weder/noch",
"5" = "eher zufrieden",
"6" = "zufrieden",
"7" = "sehr zufrieden"
)
bereinige_item_label = function(text) {
if (is.null(text) || length(text) == 0 || is.na(text[1])) return(NA_character_)
trimws(as.character(text[1]))
}
ermittle_item_text = function(daten, spalte) {
# Itemwortlaut wird zur Laufzeit aus dem label-Attribut der formr-Exportspalte gelesen
# (nicht hartkodiert, da urheberrechtlich geschuetzter Testinhalt).
if (!(spalte %in% colnames(daten))) return(NA_character_)
bereinige_item_label(attr(daten[[spalte]], "label", exact = TRUE))
}
# Datenaufbereitung ####
normtabelle_pfad = file.path(APP_VERZEICHNIS, PFAD_NORMTABELLE)
if (!file.exists(normtabelle_pfad)) {
stop(sprintf("Normtabelle nicht gefunden: '%s'.", normtabelle_pfad))
}
normtabelle_flz = read.csv(
normtabelle_pfad,
colClasses = "character",
stringsAsFactors = FALSE,
fileEncoding = "UTF-8"
)
fehlende_gruppen_check = setdiff(FLZ_GRUPPEN, unique(normtabelle_flz$gruppe))
if (length(fehlende_gruppen_check) > 0) {
stop(sprintf(
"Normtabelle unvollständig, folgende Gruppen fehlen: %s",
paste(fehlende_gruppen_check, collapse = ", ")
))
}
# UI ####
ui = fluidPage(
tags$head(
tags$meta(charset = "UTF-8"),
tags$style(HTML(app_css))
),
titlePanel("FLZ Fragebogen zur Lebenszufriedenheit"),
div(class = "input-panel",
div(style = "min-width: 360px; white-space: nowrap;",
textInput("pseudonym",
label = tagList(
"Pseudonym",
tags$span(style = "font-weight: normal; font-style: italic; font-size: 0.78em; color: #888; margin-left: 4px; white-space: nowrap;",
"optional, hat Vorrang vor Chiffre")
),
placeholder = "optional", width = "340px")
),
div(style = "min-width: 200px;",
textInput("chiffre", label = "Patientenchiffre",
placeholder = "z.B. P000123", width = "100%")
),
actionButton("btn_suchen", "Auswerten", class = "btn btn-primary btn-laden"),
div(style = "margin-left: auto;",
downloadButton("download_word", "Word-Export (.docx)")
)
),
div(style = "margin: 0 0 16px 4px;",
checkboxInput("zeige_gesamtstichprobe",
"Zusätzlich gegen Gesamtstichprobe (N=2870) vergleichen",
value = FALSE)
),
uiOutput("fehler_ui"),
uiOutput("warnung_ui"),
uiOutput("ergebnis_ui")
)
# Word-Export ####
erstelle_flz_docx = function(erg) {
doc = read_docx()
fp_titel = fp_text(color = AKZENT_FARBE, bold = TRUE, font.size = 18)
fp_abschnitt = fp_text(color = AKZENT_FARBE, bold = TRUE, font.size = 13)
fp_label = fp_text(bold = TRUE, font.size = 11)
fp_normal = fp_text(font.size = 11)
fp_warnung = fp_text(font.size = 10, color = "#B8860B")
fp_disclaimer = fp_text(font.size = 9, italic = TRUE, color = "#777777")
doc = body_add_fpar(doc, fpar(
ftext("FLZ - Fragebogen zur Lebenszufriedenheit - Einzelauswertung", fp_titel)
))
doc = body_add_fpar(doc, fpar(
ftext("Chiffre: ", fp_label), ftext(erg$chiffre, fp_normal),
ftext(" Ausfülldatum: ", fp_label), ftext(erg$ausfuelldatum_anzeige, fp_normal)
))
if (!is.null(erg$mehrfach_hinweis)) {
doc = body_add_fpar(doc, fpar(ftext(erg$mehrfach_hinweis, fp_warnung)))
}
doc = body_add_par(doc, "", style = "Normal")
doc = body_add_fpar(doc, fpar(ftext("Kopfdaten", fp_abschnitt)))
doc = body_add_fpar(doc, fpar(ftext("Geschlecht: ", fp_label), ftext(erg$geschlecht_text, fp_normal)))
doc = body_add_fpar(doc, fpar(ftext("Alter: ", fp_label), ftext(erg$alter_text, fp_normal)))
doc = body_add_fpar(doc, fpar(ftext("Normgruppe: ", fp_label), ftext(erg$gruppe_text, fp_normal)))
doc = body_add_fpar(doc, fpar(ftext("Schulabschluss: ", fp_label), ftext(erg$schulabschluss, fp_normal)))
doc = body_add_fpar(doc, fpar(ftext("Familienstand: ", fp_label), ftext(erg$familienstand, fp_normal)))
doc = body_add_fpar(doc, fpar(ftext("Haushalt: ", fp_label), ftext(erg$haushalt, fp_normal)))
doc = body_add_fpar(doc, fpar(ftext("Beruflich tätig: ", fp_label), ftext(erg$berufstaetig, fp_normal)))
doc = body_add_fpar(doc, fpar(ftext("Berufsgruppe: ", fp_label), ftext(erg$berufsgruppe, fp_normal)))
doc = body_add_par(doc, "", style = "Normal")
doc = body_add_fpar(doc, fpar(ftext("Profil: Rohwerte und Stanine-Stufen", fp_abschnitt)))
for (code in c(FLZ_DOMAENEN, "SUM")) {
z = erg$profil_zeilen[[code]]
rohwert_text = if (is.na(z$rohwert)) {
if (isTRUE(z$ist_optionale_domaene)) "nicht ausgefüllt (nicht zutreffend)" else "nicht berechenbar"
} else {
as.character(z$rohwert)
}
stanine_text = if (is.na(z$rohwert)) {
"-"
} else if (is.na(z$stanine)) {
if (identical(z$status, "ausserhalb_normstichprobe")) {
"außerhalb der digitalisierten Normstichprobe"
} else {
"keine Normgruppe"
}
} else {
paste0("Stanine ", z$stanine, if (z$stanine >= 4 && z$stanine <= 6) " (unauffällig)" else "")
}
unauffaellig = !is.na(z$rohwert) && !is.na(z$stanine) && z$stanine >= 4 && z$stanine <= 6
fp_zeile = if (unauffaellig) {
fp_text(font.size = 11, shading.color = "#E8F5E9")
} else {
fp_text(font.size = 11)
}
doc = body_add_fpar(doc, fpar(ftext(
sprintf("%s: Rohwert %s | %s", z$label, rohwert_text, stanine_text), fp_zeile
)))
}
doc = body_add_par(doc, "", style = "Normal")
if (length(erg$warnungen) > 0) {
doc = body_add_fpar(doc, fpar(ftext("Hinweise", fp_abschnitt)))
for (w in erg$warnungen) {
doc = body_add_fpar(doc, fpar(ftext(w, fp_warnung)))
}
doc = body_add_par(doc, "", style = "Normal")
}
doc = body_add_fpar(doc, fpar(ftext(FLZ_DISCLAIMER, fp_disclaimer)))
doc
}
# Server ####
server = function(input, output, session) {
observe({
query = parseQueryString(session$clientData$url_search)
if (!is.null(query$pseudonym) && nchar(trimws(query$pseudonym)) > 0) {
updateTextInput(session, "pseudonym", value = trimws(query$pseudonym))
}
})
observe({
query = parseQueryString(session$clientData$url_search)
if (!is.null(query$chiffre) && nchar(trimws(query$chiffre)) > 0) {
updateTextInput(session, "chiffre", value = toupper(trimws(query$chiffre)))
}
})
ergebnis_r = eventReactive(input$btn_suchen, {
chiffre = toupper(trimws(input$chiffre))
if (nchar(trimws(input$pseudonym)) == 0 && nchar(chiffre) == 0) {
return(list(ok = FALSE, meldung = "Bitte Chiffre oder Pseudonym eingeben."))
}
if (nchar(trimws(input$pseudonym)) == 0 && !grepl("^[A-Z][0-9]{6}$", chiffre)) {
return(list(ok = FALSE, meldung = sprintf(
"Chiffre '%s' hat kein gültiges Format (erwartet: ein Großbuchstabe + 6 Ziffern, z.B. P000123).",
chiffre
)))
}
if (!file.exists(PFAD_DOWNLOAD_SKRIPT)) {
return(list(ok = FALSE, meldung = sprintf("Download-Skript nicht gefunden:\n%s", PFAD_DOWNLOAD_SKRIPT)))
}
if (!file.exists(PFAD_PSEUDONYM_SKRIPT)) {
return(list(ok = FALSE, meldung = sprintf("Pseudonym-Skript nicht gefunden:\n%s", PFAD_PSEUDONYM_SKRIPT)))
}
ok_dl = tryCatch({
source(PFAD_DOWNLOAD_SKRIPT, local = FALSE)
list(ok = TRUE)
}, error = function(e) list(ok = FALSE, msg = e$message))
if (!ok_dl$ok) {
return(list(ok = FALSE, meldung = paste0("Fehler im Download-Skript: ", ok_dl$msg)))
}
db_ordner = local({
ordner = dirname(normalizePath(PFAD_PSEUDONYM_SKRIPT, mustWork = FALSE))
gefunden = NULL
for (i in 1:5) {
if (file.exists(file.path(ordner, "pseudonyme.db"))) {
gefunden = ordner
break
}
elternteil = dirname(ordner)
if (elternteil == ordner) break
ordner = elternteil
}
gefunden
})
alter_wd = getwd()
wd_ziel = if (!is.null(db_ordner)) db_ordner else dirname(normalizePath(PFAD_PSEUDONYM_SKRIPT, mustWork = FALSE))
setwd(wd_ziel)
on.exit(setwd(alter_wd), add = TRUE)
ok_ps = tryCatch({
source(PFAD_PSEUDONYM_SKRIPT, local = FALSE)
list(ok = TRUE)
}, error = function(e) list(ok = FALSE, msg = e$message))
if (!ok_ps$ok) {
return(list(ok = FALSE, meldung = paste0("Fehler im Pseudonym-Skript: ", ok_ps$msg)))
}
if (!exists("daten_flz", envir = .GlobalEnv)) {
return(list(ok = FALSE, meldung = "Objekt 'daten_flz' nach dem Sourcen nicht gefunden. Bitte Download-Skript prüfen."))
}
if (!exists("pseudo", envir = .GlobalEnv)) {
return(list(ok = FALSE, meldung = "Objekt 'pseudo' nach dem Sourcen nicht gefunden. Bitte Pseudonym-Skript prüfen."))
}
daten_flz = get("daten_flz", envir = .GlobalEnv)
pseudo = get("pseudo", envir = .GlobalEnv)
treffer_ps = pseudo[pseudo$chiffre == chiffre, ]
if (nchar(trimws(input$pseudonym)) > 0) {
pw_treffer = pseudo[pseudo$pseudonym == trimws(input$pseudonym), ]
if (nrow(pw_treffer) > 0) chiffre = toupper(trimws(pw_treffer$chiffre[1]))
treffer_ps = pseudo[pseudo$chiffre == chiffre, ]
}
if (nrow(treffer_ps) == 0) {
return(list(ok = FALSE, meldung = sprintf(
"Chiffre '%s' wurde in der Pseudonym-Datenbank nicht gefunden.", chiffre
)))
}
alle_session_ids = unique(treffer_ps$pseudonym)
if (nchar(trimws(input$pseudonym)) > 0) alle_session_ids = trimws(input$pseudonym)
treffer_dat = daten_flz[daten_flz$session %in% alle_session_ids, ]
if (nrow(treffer_dat) == 0) {
return(list(ok = FALSE, meldung = sprintf(
"Kein FLZ-Datensatz für Chiffre '%s' gefunden. (%d Pseudonym(e) geprüft)",
chiffre, length(alle_session_ids)
)))
}
mehrfach_hinweis = NULL
if (nrow(treffer_dat) > 1) {
n = nrow(treffer_dat)
treffer_dat = treffer_dat[order(treffer_dat$created, decreasing = TRUE), ]
datum_neu = tryCatch(
format(as.POSIXct(treffer_dat$created[1]), "%d.%m.%Y %H:%M"),
error = function(e) "unbekanntes Datum"
)
mehrfach_hinweis = sprintf(
"Mehrere Ausfüllungen gefunden (%d Einträge). Angezeigt wird die neueste vom %s.",
n, datum_neu
)
treffer_dat = treffer_dat[1, , drop = FALSE]
}
zeile = treffer_dat[1, , drop = FALSE]
ausfuelldatum = NA
ausfuelldatum_hinweis = NULL
if ("ausfuelldatum" %in% colnames(zeile)) {
ausfuelldatum = tryCatch(as.Date(zeile[["ausfuelldatum"]][1], "%d.%m.%Y"), error = function(e) NA)
}
if (is.na(ausfuelldatum) && "created" %in% colnames(zeile)) {
ausfuelldatum = tryCatch(as.Date(as.POSIXct(zeile[["created"]][1])), error = function(e) NA)
}
if (is.na(ausfuelldatum)) {
ausfuelldatum = Sys.Date()
ausfuelldatum_hinweis = "Ausfülldatum nicht in Exportdaten gefunden, Downloaddatum verwendet."
}
item_namen = unlist(lapply(FLZ_DOMAENEN, function(d) paste0("flz_", tolower(d), "_", 1:7)))
item_werte = setNames(vapply(item_namen, function(n) {
if (!(n %in% colnames(zeile))) return(NA_real_)
extrahiere_stufe(zeile[[n]])
}, numeric(1)), item_namen)
scores = berechne_flz_scores(item_werte)
item_info = lapply(FLZ_DOMAENEN, function(dom) {
lapply(1:7, function(i) {
spalte = paste0("flz_", tolower(dom), "_", i)
list(
nr = i,
spalte = spalte,
stufe = item_werte[[spalte]],
text = ermittle_item_text(daten_flz, spalte)
)
})
})
names(item_info) = FLZ_DOMAENEN
geschlecht_text = if ("flz_geschlecht" %in% colnames(zeile)) {
extrahiere_klartext(zeile[["flz_geschlecht"]][1])
} else {
NA_character_
}
alter_roh = if ("flz_alter" %in% colnames(zeile)) zeile[["flz_alter"]][1] else NA
alter_num = suppressWarnings(as.numeric(as.character(alter_roh)))
gruppe_info = bestimme_gruppe(geschlecht_text, alter_num)
zeige_gesamt = isTRUE(input$zeige_gesamtstichprobe)
warnungen = c()
if (!is.null(gruppe_info$warnung)) warnungen = c(warnungen, gruppe_info$warnung)
if (!is.null(ausfuelldatum_hinweis)) warnungen = c(warnungen, ausfuelldatum_hinweis)
if (isTRUE(scores$ueberschreitung)) {
warnungen = c(warnungen, sprintf(
"Mehr als 7 der 70 Items fehlen (%d fehlend). Alle Testwerte (10 Domänen + FLZ-SUM) sind nicht berechenbar.",
scores$n_fehlend_gesamt
))
} else if (scores$n_fehlend_gesamt > 0) {
warnungen = c(warnungen, sprintf("%d von 70 Items wurden nicht beantwortet.", scores$n_fehlend_gesamt))
}
profil_zeilen = list()
for (dom in FLZ_DOMAENEN) {
rohwert = scores$domaenen[[dom]]
st_haupt = if (gruppe_info$ok) {
bestimme_stanine(rohwert, normtabelle_flz, gruppe_info$gruppe, dom)
} else {
list(stanine = NA_integer_, status = "keine_gruppe")
}
st_gesamt = if (zeige_gesamt) {
bestimme_stanine(rohwert, normtabelle_flz, "Gesamtstichprobe N=2870", dom)
} else {
NULL
}
profil_zeilen[[dom]] = list(
code = dom,
label = FLZ_DOMAENEN_NAMEN[[dom]],
rohwert = rohwert,
stanine = st_haupt$stanine,
status = st_haupt$status,
stanine_gesamt = if (!is.null(st_gesamt)) st_gesamt$stanine else NA_integer_,
ist_optionale_domaene = dom %in% FLZ_OPTIONALE_DOMAENEN
)
}
rohwert_sum = scores$sum
st_sum_haupt = if (gruppe_info$ok) {
bestimme_stanine(rohwert_sum, normtabelle_flz, gruppe_info$gruppe, "SUM")
} else {
list(stanine = NA_integer_, status = "keine_gruppe")
}
st_sum_gesamt = if (zeige_gesamt) {
bestimme_stanine(rohwert_sum, normtabelle_flz, "Gesamtstichprobe N=2870", "SUM")
} else {
NULL
}
profil_zeilen[["SUM"]] = list(
code = "SUM",
label = "FLZ-SUM",
rohwert = rohwert_sum,
stanine = st_sum_haupt$stanine,
status = st_sum_haupt$status,
stanine_gesamt = if (!is.null(st_sum_gesamt)) st_sum_gesamt$stanine else NA_integer_,
ist_optionale_domaene = FALSE
)
list(
ok = TRUE,
chiffre = chiffre,
ausfuelldatum = ausfuelldatum,
ausfuelldatum_anzeige = format(ausfuelldatum, "%d.%m.%Y"),
mehrfach_hinweis = mehrfach_hinweis,
geschlecht_text = ifelse(is.na(geschlecht_text) || geschlecht_text == "", "k. A.", geschlecht_text),
alter_text = ifelse(is.na(alter_num), "k. A.", as.character(alter_num)),
gruppe_info = gruppe_info,
gruppe_text = ifelse(gruppe_info$ok, gruppe_info$gruppe, "keine Zuordnung möglich"),
schulabschluss = if ("flz_schulabschluss" %in% colnames(zeile)) extrahiere_klartext(zeile[["flz_schulabschluss"]][1]) else "k. A.",
familienstand = if ("flz_familienstand" %in% colnames(zeile)) extrahiere_klartext(zeile[["flz_familienstand"]][1]) else "k. A.",
haushalt = if ("flz_haushalt" %in% colnames(zeile)) extrahiere_klartext(zeile[["flz_haushalt"]][1]) else "k. A.",
berufstaetig = if ("flz_berufstaetig" %in% colnames(zeile)) extrahiere_klartext(zeile[["flz_berufstaetig"]][1]) else "k. A.",
berufsgruppe = if ("flz_berufsgruppe" %in% colnames(zeile)) extrahiere_klartext(zeile[["flz_berufsgruppe"]][1]) else "k. A.",
scores = scores,
profil_zeilen = profil_zeilen,
item_info = item_info,
zeige_gesamt = zeige_gesamt,
warnungen = warnungen,
meldung = NULL
)
})
baue_profil_plot = function(erg) {
profil_reihenfolge = c(FLZ_DOMAENEN, "SUM")
daten = do.call(rbind, lapply(profil_reihenfolge, function(code) {
z = erg$profil_zeilen[[code]]
data.frame(
label = z$label,
code = code,
stanine = if (is.na(z$rohwert)) NA_real_ else as.numeric(z$stanine),
stringsAsFactors = FALSE
)
}))
daten$label = factor(daten$label, levels = rev(unique(daten$label)))
daten_plot = daten[!is.na(daten$stanine), ]
ggplot() +
annotate("rect", xmin = 3.5, xmax = 6.5, ymin = -Inf, ymax = Inf,
fill = "#E8F5E9", alpha = 0.6) +
geom_point(data = daten_plot, aes(x = stanine, y = label),
color = AKZENT_FARBE, size = 3, na.rm = TRUE) +
scale_x_continuous(limits = c(1, 9), breaks = 1:9) +
labs(x = "Stanine", y = NULL,
title = "FLZ-Profil (Stanine 4-6 = unauffälliger Bereich)") +
theme_minimal(base_size = 12)
}
output$fehler_ui = renderUI({
req(input$btn_suchen)
erg = ergebnis_r()
if (!isTRUE(erg$ok)) div(class = "alert-fehler", erg$meldung)
})
output$warnung_ui = renderUI({
req(input$btn_suchen)
erg = ergebnis_r()
if (!isTRUE(erg$ok)) return(NULL)
blocks = list()
if (!is.null(erg$mehrfach_hinweis)) blocks = c(blocks, list(div(class = "alert-warnung", erg$mehrfach_hinweis)))
if (length(erg$warnungen) > 0) {
for (w in erg$warnungen) blocks = c(blocks, list(div(class = "alert-warnung", w)))
}
if (length(blocks) == 0) return(NULL)
div(blocks)
})
output$ergebnis_ui = renderUI({
req(input$btn_suchen)
erg = ergebnis_r()
if (!isTRUE(erg$ok)) return(NULL)
profil_reihenfolge = c(FLZ_DOMAENEN, "SUM")
zeilen_ui = lapply(profil_reihenfolge, function(code) {
z = erg$profil_zeilen[[code]]
rohwert_anzeige = if (is.na(z$rohwert)) {
if (isTRUE(z$ist_optionale_domaene)) "nicht ausgefüllt (nicht zutreffend)" else "nicht berechenbar"
} else {
as.character(z$rohwert)
}
stanine_ui = if (is.na(z$rohwert)) {
span("-")
} else if (is.na(z$stanine)) {
span(if (identical(z$status, "ausserhalb_normstichprobe"))
"außerhalb der digitalisierten Normstichprobe"
else if (identical(z$status, "keine_gruppe"))
"keine Normgruppe"
else "-")
} else {
span(class = paste("stanine-badge", stanine_badge_klasse(z$stanine)),
paste0("Stanine ", z$stanine, if (z$stanine >= 4 && z$stanine <= 6) " (unauffällig)" else ""))
}
gesamt_ui = NULL
if (isTRUE(erg$zeige_gesamt)) {
gesamt_text = if (is.na(z$rohwert)) {
"-"
} else if (is.na(z$stanine_gesamt)) {
"n. v."
} else {
paste0("Gesamtstichprobe: Stanine ", z$stanine_gesamt)
}
gesamt_ui = span(style = "margin-left: 10px; color: #777; font-size: 0.85em;", gesamt_text)
}
div(class = "profil-zeile",
div(style = "min-width: 220px; font-weight: 600;", z$label),
div(style = "min-width: 90px;", rohwert_anzeige),
div(stanine_ui, gesamt_ui)
)
})
div(
div(class = "abschnitt-karte",
div(class = "abschnitt-titel", "Kopfdaten"),
div(style = "margin-bottom: 6px;",
tags$strong("Chiffre: "), erg$chiffre,
tags$span(style = "color: #ccc; margin: 0 8px;", "|"),
tags$strong("Ausfülldatum: "), erg$ausfuelldatum_anzeige
),
div(style = "margin-bottom: 4px;",
tags$strong("Geschlecht: "), erg$geschlecht_text,
tags$span(style = "color: #ccc; margin: 0 8px;", "|"),
tags$strong("Alter: "), erg$alter_text,
tags$span(style = "color: #ccc; margin: 0 8px;", "|"),
tags$strong("Normgruppe: "), erg$gruppe_text
),
div(style = "margin-bottom: 4px;", tags$strong("Schulabschluss: "), erg$schulabschluss),
div(style = "margin-bottom: 4px;", tags$strong("Familienstand: "), erg$familienstand),
div(style = "margin-bottom: 4px;", tags$strong("Haushalt: "), erg$haushalt),
div(style = "margin-bottom: 4px;", tags$strong("Beruflich tätig: "), erg$berufstaetig),
div(style = "margin-bottom: 4px;", tags$strong("Berufsgruppe: "), erg$berufsgruppe)
),
div(class = "abschnitt-karte",
div(class = "abschnitt-titel", "Profil: Rohwerte und Stanine"),
div(class = "profil-zeile", style = "font-weight: 700; color: #555; border-bottom: 2px solid #ddd;",
div(style = "min-width: 220px;", "Domäne"),
div(style = "min-width: 90px;", "Rohwert"),
div("Stanine")
),
zeilen_ui
),
div(class = "abschnitt-karte",
div(class = "abschnitt-titel", "Profildarstellung"),
plotOutput("profil_plot", height = "420px")
),
div(class = "abschnitt-karte",
div(class = "abschnitt-titel", "Items pro Skala"),
lapply(FLZ_DOMAENEN, function(dom) {
items_dom = erg$item_info[[dom]]
rohwert_dom = erg$profil_zeilen[[dom]]$rohwert
rohwert_anzeige = if (is.na(rohwert_dom)) {
if (isTRUE(erg$profil_zeilen[[dom]]$ist_optionale_domaene)) "nicht ausgefüllt (nicht zutreffend)" else "nicht berechenbar"
} else {
as.character(rohwert_dom)
}
tags$details(
tags$summary(sprintf("%s (Rohwert: %s)", FLZ_DOMAENEN_NAMEN[[dom]], rohwert_anzeige)),
lapply(items_dom, function(it) {
stufe_anzeige = if (is.na(it$stufe)) {
"fehlend"
} else {
paste0(it$stufe, " = ", FLZ_STUFEN_TEXT[[as.character(it$stufe)]])
}
item_text_anzeige = if (is.na(it$text)) sprintf("Item %s.%d", dom, it$nr) else it$text
div(class = "item-zeile",
span(class = "item-nr", it$nr),
span(class = "item-text", item_text_anzeige),
span(style = paste0("font-weight: 600; color: ", AKZENT_FARBE, "; white-space: nowrap;"),
stufe_anzeige)
)
})
)
})
),
div(class = "abschnitt-karte",
div(class = "abschnitt-titel", "Hinweis zur Interpretation"),
p(style = "font-size: 0.85em; color: #555; line-height: 1.5;", FLZ_DISCLAIMER)
)
)
})
output$profil_plot = renderPlot({
erg = ergebnis_r()
req(isTRUE(erg$ok))
baue_profil_plot(erg)
})
output$download_word = downloadHandler(
filename = function() {
erg = tryCatch(ergebnis_r(), error = function(e) NULL)
if (is.null(erg) || !isTRUE(erg$ok)) return("FLZ_Auswertung.docx")
chiffre_esc = gsub("[^A-Za-z0-9]", "", erg$chiffre)
ausfuelldatum_fn = tryCatch(
format(as.Date(erg$ausfuelldatum, "%d.%m.%Y"), "%Y%m%d"),
error = function(e) format(Sys.Date(), "%Y%m%d")
)
paste0("FLZ_", chiffre_esc, "_", ausfuelldatum_fn, ".docx")
},
content = function(file) {
erg = tryCatch(ergebnis_r(), error = function(e) NULL)
if (is.null(erg) || !isTRUE(erg$ok)) {
doc = read_docx()
doc = body_add_par(doc,
"Kein Datensatz geladen. Bitte zuerst Chiffre oder Pseudonym eingeben und 'Auswerten' klicken.",
style = "Normal")
print(doc, target = file)
return()
}
doc = tryCatch(
erstelle_flz_docx(erg),
error = function(e) {
err_doc = read_docx()
body_add_par(err_doc,
paste0("Fehler beim Erstellen des Word-Dokuments: ", e$message),
style = "Normal")
}
)
print(doc, target = file)
}
)
}
# Start ####
shinyApp(ui = ui, server = server)

136
FLZ/normtabellen_flz.csv Normal file
View file

@ -0,0 +1,136 @@
"gruppe","stanine","GES","ARB","FIN","FRE","EHE","KIN","PER","SEX","BEK","WOH","SUM"
"Gesamtstichprobe N=2870","ST1","7-21","7-15","7-15","7-19","7-24","7-26","7-26","7-19","7-25","7-23","49-189"
"Gesamtstichprobe N=2870","ST2","22-27","16-25","16-21","20-26","25-28","27-28","27-30","20-24","26-29","24-28","190-209"
"Gesamtstichprobe N=2870","ST3","28-33","26-28","22-27","27-29","29-34","29-34","31-34","25-28","30-32","29-33","210-232"
"Gesamtstichprobe N=2870","ST4","34-37","29-34","28-33","30-34","35-39","35-39","35-38","29-32","33-36","34-36","233-251"
"Gesamtstichprobe N=2870","ST5","38-41","35-39","34-37","35-39","40-42","40-41","39-41","33-38","37-39","37-40","252-269"
"Gesamtstichprobe N=2870","ST6","42-43","40-42","38-41","40-42","43-45","42-43","42-42","39-41","40-41","41-43","270-283"
"Gesamtstichprobe N=2870","ST7","44-46","43-44","42-42","43-45","46-47","44-46","43-44","42-43","42-43","44-45","284-295"
"Gesamtstichprobe N=2870","ST8","47-48","45-48","43-46","46-48","48-48","47-48","45-46","44-46","44-46","46-48","296-308"
"Gesamtstichprobe N=2870","ST9","49-49","49-49","47-49","49-49","49-49","49-49","47-49","47-49","47-49","49-49","309-343"
"Männer 14-25","ST1","7-30","7-16","7-14","7-21","7-26","7-23","7-29","7-21","7-27","7-18","49-209"
"Männer 14-25","ST2","31-35","17-24","15-20","22-28","27-27","24-26","30-33","22-26","28-31","19-25","210-232"
"Männer 14-25","ST3","36-39","25-30","21-24","29-33","28-32","27-29","34-36","27-29","32-34","26-31","233-240"
"Männer 14-25","ST4","40-42","31-36","25-29","34-36","33-37","30-34","37-39","30-34","35-36","32-34","241-254"
"Männer 14-25","ST5","43-44","37-40","30-35","37-40","38-41","35-40","40-41","35-38","37-39","35-38","255-270"
"Männer 14-25","ST6","45-47","41-43","36-39","41-42","42-44","41-45","42-43","39-42","40-41","39-41","271-286"
"Männer 14-25","ST7","48-48","44-45","40-41","43-46","45-47","46-48","44-45","43-46","42-44","42-44","287-293"
"Männer 14-25","ST8","49-49","46-48","42-43","47-48","48-48","49-49","46-47","47-48","45-48","45-48","294-306"
"Männer 14-25","ST9","-","49-49","44-49","49-49","49-49","-","48-49","49-49","49-49","49-49","307-343"
"Männer 26-35","ST1","7-27","7-19","7-15","7-20","7-25","7-27","7-26","7-23","7-23","7-23","49-195"
"Männer 26-35","ST2","28-32","20-27","16-21","21-24","26-29","28-28","27-31","24-28","24-28","24-26","196-216"
"Männer 26-35","ST3","33-37","28-32","22-28","25-28","30-34","29-35","32-36","29-33","29-32","27-30","217-236"
"Männer 26-35","ST4","38-41","33-36","29-33","29-34","35-41","36-39","37-40","34-37","33-35","31-35","237-257"
"Männer 26-35","ST5","42-43","37-39","34-36","35-38","42-42","40-41","41-41","38-41","36-39","36-39","258-273"
"Männer 26-35","ST6","44-45","40-42","37-40","39-41","43-45","42-43","42-43","42-42","40-41","40-42","274-286"
"Männer 26-35","ST7","46-47","43-45","41-43","42-43","46-47","44-46","44-45","43-45","42-44","43-45","287-300"
"Männer 26-35","ST8","48-48","46-48","44-45","44-46","48-48","47-48","46-46","46-48","45-46","46-48","301-310"
"Männer 26-35","ST9","49-49","49-49","46-49","47-49","49-49","49-49","47-49","49-49","47-49","49-49","311-343"
"Männer 36-45","ST1","7-25","7-17","7-13","7-19","7-23","7-22","7-27","7-23","7-22","7-21","49-187"
"Männer 36-45","ST2","26-29","18-25","14-20","20-24","24-28","23-27","28-29","24-27","23-27","22-27","188-202"
"Männer 36-45","ST3","30-35","26-30","21-27","25-28","29-33","28-31","30-33","28-30","28-31","28-31","203-225"
"Männer 36-45","ST4","36-39","31-35","28-33","29-32","34-39","32-36","34-37","31-35","32-35","32-35","226-252"
"Männer 36-45","ST5","40-41","36-40","34-38","33-37","40-42","37-40","38-41","36-39","36-38","36-39","253-271"
"Männer 36-45","ST6","42-43","41-42","39-41","38-41","43-44","41-42","42-42","40-42","39-41","40-42","272-285"
"Männer 36-45","ST7","44-46","43-44","42-42","42-43","45-46","43-45","43-44","43-44","42-43","43-45","286-296"
"Männer 36-45","ST8","47-48","45-47","43-45","44-46","47-48","46-48","45-46","45-48","44-45","46-48","297-310"
"Männer 36-45","ST9","49-49","48-49","46-49","47-49","49-49","49-49","47-49","49-49","46-49","49-49","311-343"
"Männer 46-55","ST1","7-21","7-17","7-12","7-20","7-27","7-20","7-26","7-19","7-26","7-24","49-187"
"Männer 46-55","ST2","22-28","18-25","13-17","21-25","28-30","21-26","27-29","20-26","27-28","25-28","188-203"
"Männer 46-55","ST3","29-33","26-29","18-25","26-29","31-35","27-33","30-33","27-30","29-32","29-33","204-222"
"Männer 46-55","ST4","34-37","30-34","26-31","30-34","36-41","34-38","34-37","31-35","33-35","34-37","223-247"
"Männer 46-55","ST5","38-41","35-40","32-37","35-39","42-42","39-41","38-41","36-40","36-38","38-41","248-270"
"Männer 46-55","ST6","42-43","41-42","38-41","40-41","43-46","42-43","42-42","41-42","39-41","42-42","271-286"
"Männer 46-55","ST7","44-45","43-46","42-42","42-43","47-47","44-46","43-44","43-43","42-43","43-45","287-297"
"Männer 46-55","ST8","46-48","47-48","43-47","44-48","48-48","47-48","45-46","44-46","44-44","46-48","298-309"
"Männer 46-55","ST9","49-49","49-49","48-49","49-49","49-49","49-49","47-49","47-49","45-49","49-49","310-343"
"Männer 56-65","ST1","7-20","7-11","7-15","7-19","7-27","7-27","7-27","7-23","7-24","7-26","49-185"
"Männer 56-65","ST2","21-25","12-18","16-22","20-27","28-33","28-32","28-32","24-27","25-30","27-30","186-214"
"Männer 56-65","ST3","26-31","19-27","23-28","28-30","34-39","33-36","33-35","28-28","31-33","31-34","215-236"
"Männer 56-65","ST4","32-35","28-28","29-34","31-37","40-41","37-40","36-38","29-33","34-37","35-38","237-255"
"Männer 56-65","ST5","36-39","29-37","35-38","38-41","42-44","41-42","39-41","34-38","38-39","39-41","256-272"
"Männer 56-65","ST6","40-42","38-41","39-41","42-43","45-46","43-43","42-42","39-41","40-42","42-44","273-286"
"Männer 56-65","ST7","43-43","42-44","42-43","44-47","47-47","44-46","43-44","42-42","43-43","45-46","287-298"
"Männer 56-65","ST8","44-46","45-48","44-47","48-48","48-48","47-48","45-46","43-44","44-45","47-48","299-311"
"Männer 56-65","ST9","47-49","49-49","48-49","49-49","49-49","49-49","47-49","45-49","46-49","49-49","312-343"
"Männer 66-75","ST1","7-19","7-15","7-19","7-25","7-27","7-26","7-28","7-15","7-25","7-27","49-192"
"Männer 66-75","ST2","20-23","16-21","20-26","26-27","28-29","27-30","29-31","16-20","26-28","28-31","193-215"
"Männer 66-75","ST3","24-28","22-27","27-31","28-30","30-36","31-34","32-35","21-25","29-32","32-34","216-232"
"Männer 66-75","ST4","29-34","28-31","32-35","31-34","37-40","35-38","36-37","26-28","33-35","35-38","233-246"
"Männer 66-75","ST5","35-37","32-35","36-37","35-40","41-42","39-41","38-40","29-32","36-38","39-41","247-261"
"Männer 66-75","ST6","38-41","36-39","38-41","41-43","43-45","42-43","41-42","33-37","39-41","42-43","262-276"
"Männer 66-75","ST7","42-43","40-42","42-42","44-47","46-47","44-46","43-44","38-41","42-43","44-45","277-289"
"Männer 66-75","ST8","44-45","43-46","43-45","48-48","48-48","47-48","45-46","42-42","44-45","46-48","290-297"
"Männer 66-75","ST9","46-49","47-49","46-49","49-49","49-49","49-49","47-49","43-49","46-49","49-49","298-343"
"Männer über 75","ST1","7-21","7-18","7-22","7-21","7-28","7-28","7-28","7-12","7-29","7-27","49-203"
"Männer über 75","ST2","22-26","19-24","23-31","22-27","29-33","29-31","29-32","13-19","30-30","28-28","204-214"
"Männer über 75","ST3","27-28","25-29","32-34","28-33","34-36","32-33","33-35","20-26","31-32","29-34","215-233"
"Männer über 75","ST4","29-33","30-33","35-37","34-37","37-41","34-36","36-39","27-28","33-35","35-37","234-249"
"Männer über 75","ST5","34-36","34-37","38-40","38-41","42-44","37-41","40-41","29-29","36-38","38-41","250-262"
"Männer über 75","ST6","37-40","38-43","41-42","42-45","45-47","42-43","42-43","30-33","39-42","42-44","263-280"
"Männer über 75","ST7","41-43","44-47","43-47","46-48","48-48","44-45","44-45","34-35","43-45","45-46","281-302"
"Männer über 75","ST8","44-45","48-49","48-48","49-49","49-49","46-48","46-47","36-41","46-48","47-48","303-305"
"Männer über 75","ST9","46-49","-","49-49","-","-","49-49","48-49","42-49","49-49","49-49","306-343"
"Frauen 14-25","ST1","7-22","7-15","7-14","7-18","7-27","-","7-22","7-20","7-25","7-21","49-183"
"Frauen 14-25","ST2","23-27","16-26","15-21","19-25","28-29","7-27","23-28","21-25","26-28","22-25","184-208"
"Frauen 14-25","ST3","28-34","27-29","22-26","26-29","30-35","28-30","29-33","26-28","29-32","26-30","209-229"
"Frauen 14-25","ST4","35-40","30-35","27-30","30-34","36-39","31-37","34-38","29-33","33-36","31-35","230-250"
"Frauen 14-25","ST5","41-42","36-39","31-35","35-38","40-42","38-41","39-41","34-39","37-38","36-38","251-265"
"Frauen 14-25","ST6","43-45","40-42","36-38","39-42","43-45","42-45","42-42","40-42","39-41","39-41","266-281"
"Frauen 14-25","ST7","46-48","43-44","39-42","43-44","46-48","46-47","43-44","43-44","42-43","42-44","282-290"
"Frauen 14-25","ST8","49-49","45-47","43-44","45-48","49-49","48-48","45-46","45-46","44-46","45-46","291-300"
"Frauen 14-25","ST9","-","48-49","45-49","49-49","-","49-49","47-49","47-49","47-49","47-49","301-343"
"Frauen 26-35","ST1","7-23","7-16","7-17","7-19","7-24","7-28","7-25","7-23","7-25","7-22","49-188"
"Frauen 26-35","ST2","24-30","17-22","18-22","20-24","25-28","29-32","26-30","24-27","26-29","23-27","189-210"
"Frauen 26-35","ST3","31-35","23-28","23-26","25-28","29-35","33-37","31-35","28-31","30-33","28-31","211-236"
"Frauen 26-35","ST4","36-40","29-33","27-31","29-33","36-40","38-41","36-39","32-36","34-36","32-35","237-254"
"Frauen 26-35","ST5","41-42","34-38","32-36","34-38","41-42","42-42","40-41","37-40","37-39","36-39","255-270"
"Frauen 26-35","ST6","43-44","39-41","37-40","39-41","43-45","43-44","42-42","41-42","40-41","40-42","271-285"
"Frauen 26-35","ST7","45-47","42-44","41-42","42-42","46-47","45-47","43-44","43-44","42-43","43-45","286-298"
"Frauen 26-35","ST8","48-48","45-48","43-46","43-46","48-48","48-48","45-47","45-48","44-45","46-47","299-308"
"Frauen 26-35","ST9","49-49","49-49","47-49","47-49","49-49","49-49","48-49","49-49","46-49","48-49","309-343"
"Frauen 36-45","ST1","7-24","7-19","7-14","7-19","7-21","7-27","7-26","7-21","7-25","7-24","49-187"
"Frauen 36-45","ST2","25-29","20-25","15-21","20-25","22-28","28-30","27-30","22-27","26-29","25-28","188-211"
"Frauen 36-45","ST3","30-34","26-28","22-28","26-29","29-33","31-35","31-34","28-31","30-33","29-34","212-235"
"Frauen 36-45","ST4","35-38","29-34","29-34","30-34","34-40","36-39","35-38","32-35","34-36","35-37","236-255"
"Frauen 36-45","ST5","39-41","35-39","35-38","35-38","41-42","40-41","39-41","36-40","37-39","38-41","256-272"
"Frauen 36-45","ST6","42-43","40-41","39-41","39-41","43-44","42-44","42-42","41-42","40-41","42-43","273-284"
"Frauen 36-45","ST7","44-45","42-43","42-42","42-43","45-46","45-46","43-43","43-43","42-43","44-45","285-296"
"Frauen 36-45","ST8","46-48","44-47","43-45","44-47","47-48","47-48","44-46","44-46","44-45","46-48","297-313"
"Frauen 36-45","ST9","49-49","48-49","46-49","48-49","49-49","49-49","47-49","47-49","46-49","49-49","314-343"
"Frauen 46-55","ST1","7-21","7-11","7-13","7-19","7-21","7-27","7-25","7-19","7-24","7-26","49-186"
"Frauen 46-55","ST2","22-28","12-24","14-21","20-26","22-27","28-31","26-30","20-25","25-29","27-29","187-211"
"Frauen 46-55","ST3","29-33","25-28","22-29","27-29","28-34","32-35","31-34","26-28","30-33","30-34","212-231"
"Frauen 46-55","ST4","34-37","29-34","30-34","30-34","35-38","36-38","35-37","29-32","34-36","35-37","232-249"
"Frauen 46-55","ST5","38-41","35-39","35-38","35-38","39-41","39-41","38-41","33-37","37-39","38-41","250-267"
"Frauen 46-55","ST6","42-42","40-42","39-41","39-42","42-44","42-43","42-42","38-41","40-41","42-44","268-287"
"Frauen 46-55","ST7","43-44","43-44","42-43","43-45","45-47","44-47","43-45","42-42","42-43","45-47","288-303"
"Frauen 46-55","ST8","45-47","45-48","44-48","46-48","48-48","48-48","46-47","43-45","44-45","48-48","304-313"
"Frauen 46-55","ST9","48-49","49-49","49-49","49-49","49-49","49-49","48-49","46-49","46-49","49-49","314-343"
"Frauen 56-65","ST1","7-20","7-12","7-17","7-24","7-23","7-27","7-26","7-19","7-24","7-25","49-192"
"Frauen 56-65","ST2","21-26","13-26","18-24","25-27","24-27","28-29","27-30","20-21","25-29","26-28","193-207"
"Frauen 56-65","ST3","27-30","27-27","25-28","28-30","28-28","30-34","31-34","22-27","30-33","29-34","208-233"
"Frauen 56-65","ST4","31-35","28-28","29-34","31-35","29-37","35-38","35-38","28-29","34-37","35-39","234-249"
"Frauen 56-65","ST5","36-39","29-32","35-37","36-40","38-41","39-41","39-41","30-34","38-39","40-41","250-269"
"Frauen 56-65","ST6","40-42","33-40","38-41","41-43","42-43","42-44","42-42","35-39","40-42","42-44","270-280"
"Frauen 56-65","ST7","43-44","41-42","42-42","44-46","44-46","45-46","43-44","40-41","43-44","45-47","281-292"
"Frauen 56-65","ST8","45-46","43-47","43-45","47-48","47-48","47-48","45-46","42-42","45-47","48-48","293-308"
"Frauen 56-65","ST9","47-49","48-49","46-49","49-49","49-49","49-49","47-49","43-49","48-49","49-49","309-343"
"Frauen 66-75","ST1","7-20","7-9","7-18","7-21","7-25","7-27","7-26","7-19","7-25","7-24","49-190"
"Frauen 66-75","ST2","21-23","10-17","19-23","22-27","26-27","28-28","27-29","20-20","26-28","25-30","191-206"
"Frauen 66-75","ST3","24-28","18-24","24-29","28-31","28-28","29-33","30-33","21-24","29-32","31-35","207-226"
"Frauen 66-75","ST4","29-34","25-27","30-34","32-35","29-33","34-39","34-37","25-27","33-37","36-39","227-249"
"Frauen 66-75","ST5","35-37","28-28","35-38","36-41","34-40","40-41","38-40","28-29","38-40","40-41","250-262"
"Frauen 66-75","ST6","38-41","29-31","39-41","42-44","41-45","42-43","41-42","30-33","41-42","42-43","263-271"
"Frauen 66-75","ST7","42-43","32-42","42-42","45-48","46-48","44-45","43-43","34-39","43-44","44-46","272-290"
"Frauen 66-75","ST8","44-47","43-47","43-46","49-49","49-49","46-48","44-46","40-43","45-48","47-48","291-296"
"Frauen 66-75","ST9","48-49","48-49","47-49","-","-","49-49","47-49","44-49","49-49","49-49","297-343"
"Frauen über 75","ST1","7-14","7-9","7-23","7-25","7-24","7-27","7-26","7-9","7-26","7-26","49-188"
"Frauen über 75","ST2","15-19","10-17","24-27","26-28","25-26","28-28","27-27","10-21","27-27","27-30","189-202"
"Frauen über 75","ST3","20-25","18-22","28-31","29-32","27-27","29-34","28-32","22-26","28-31","31-34","203-214"
"Frauen über 75","ST4","26-29","23-27","32-35","33-35","28-29","35-37","33-35","27-27","32-37","35-39","215-246"
"Frauen über 75","ST5","30-34","28-31","36-39","36-41","30-33","38-41","36-40","28-28","38-40","40-42","247-257"
"Frauen über 75","ST6","35-37","32-35","40-41","42-44","34-43","42-43","41-42","29-29","41-43","43-44","258-276"
"Frauen über 75","ST7","38-44","36-37","42-43","45-48","44-46","44-47","43-46","30-31","44-46","45-47","277-292"
"Frauen über 75","ST8","45-47","38-40","44-48","49-49","47-48","48-48","47-48","32-41","47-48","48-48","293-306"
"Frauen über 75","ST9","48-49","41-49","49-49","-","49-49","49-49","49-49","42-49","49-49","49-49","307-343"
1 gruppe stanine GES ARB FIN FRE EHE KIN PER SEX BEK WOH SUM
2 Gesamtstichprobe N=2870 ST1 7-21 7-15 7-15 7-19 7-24 7-26 7-26 7-19 7-25 7-23 49-189
3 Gesamtstichprobe N=2870 ST2 22-27 16-25 16-21 20-26 25-28 27-28 27-30 20-24 26-29 24-28 190-209
4 Gesamtstichprobe N=2870 ST3 28-33 26-28 22-27 27-29 29-34 29-34 31-34 25-28 30-32 29-33 210-232
5 Gesamtstichprobe N=2870 ST4 34-37 29-34 28-33 30-34 35-39 35-39 35-38 29-32 33-36 34-36 233-251
6 Gesamtstichprobe N=2870 ST5 38-41 35-39 34-37 35-39 40-42 40-41 39-41 33-38 37-39 37-40 252-269
7 Gesamtstichprobe N=2870 ST6 42-43 40-42 38-41 40-42 43-45 42-43 42-42 39-41 40-41 41-43 270-283
8 Gesamtstichprobe N=2870 ST7 44-46 43-44 42-42 43-45 46-47 44-46 43-44 42-43 42-43 44-45 284-295
9 Gesamtstichprobe N=2870 ST8 47-48 45-48 43-46 46-48 48-48 47-48 45-46 44-46 44-46 46-48 296-308
10 Gesamtstichprobe N=2870 ST9 49-49 49-49 47-49 49-49 49-49 49-49 47-49 47-49 47-49 49-49 309-343
11 Männer 14-25 ST1 7-30 7-16 7-14 7-21 7-26 7-23 7-29 7-21 7-27 7-18 49-209
12 Männer 14-25 ST2 31-35 17-24 15-20 22-28 27-27 24-26 30-33 22-26 28-31 19-25 210-232
13 Männer 14-25 ST3 36-39 25-30 21-24 29-33 28-32 27-29 34-36 27-29 32-34 26-31 233-240
14 Männer 14-25 ST4 40-42 31-36 25-29 34-36 33-37 30-34 37-39 30-34 35-36 32-34 241-254
15 Männer 14-25 ST5 43-44 37-40 30-35 37-40 38-41 35-40 40-41 35-38 37-39 35-38 255-270
16 Männer 14-25 ST6 45-47 41-43 36-39 41-42 42-44 41-45 42-43 39-42 40-41 39-41 271-286
17 Männer 14-25 ST7 48-48 44-45 40-41 43-46 45-47 46-48 44-45 43-46 42-44 42-44 287-293
18 Männer 14-25 ST8 49-49 46-48 42-43 47-48 48-48 49-49 46-47 47-48 45-48 45-48 294-306
19 Männer 14-25 ST9 - 49-49 44-49 49-49 49-49 - 48-49 49-49 49-49 49-49 307-343
20 Männer 26-35 ST1 7-27 7-19 7-15 7-20 7-25 7-27 7-26 7-23 7-23 7-23 49-195
21 Männer 26-35 ST2 28-32 20-27 16-21 21-24 26-29 28-28 27-31 24-28 24-28 24-26 196-216
22 Männer 26-35 ST3 33-37 28-32 22-28 25-28 30-34 29-35 32-36 29-33 29-32 27-30 217-236
23 Männer 26-35 ST4 38-41 33-36 29-33 29-34 35-41 36-39 37-40 34-37 33-35 31-35 237-257
24 Männer 26-35 ST5 42-43 37-39 34-36 35-38 42-42 40-41 41-41 38-41 36-39 36-39 258-273
25 Männer 26-35 ST6 44-45 40-42 37-40 39-41 43-45 42-43 42-43 42-42 40-41 40-42 274-286
26 Männer 26-35 ST7 46-47 43-45 41-43 42-43 46-47 44-46 44-45 43-45 42-44 43-45 287-300
27 Männer 26-35 ST8 48-48 46-48 44-45 44-46 48-48 47-48 46-46 46-48 45-46 46-48 301-310
28 Männer 26-35 ST9 49-49 49-49 46-49 47-49 49-49 49-49 47-49 49-49 47-49 49-49 311-343
29 Männer 36-45 ST1 7-25 7-17 7-13 7-19 7-23 7-22 7-27 7-23 7-22 7-21 49-187
30 Männer 36-45 ST2 26-29 18-25 14-20 20-24 24-28 23-27 28-29 24-27 23-27 22-27 188-202
31 Männer 36-45 ST3 30-35 26-30 21-27 25-28 29-33 28-31 30-33 28-30 28-31 28-31 203-225
32 Männer 36-45 ST4 36-39 31-35 28-33 29-32 34-39 32-36 34-37 31-35 32-35 32-35 226-252
33 Männer 36-45 ST5 40-41 36-40 34-38 33-37 40-42 37-40 38-41 36-39 36-38 36-39 253-271
34 Männer 36-45 ST6 42-43 41-42 39-41 38-41 43-44 41-42 42-42 40-42 39-41 40-42 272-285
35 Männer 36-45 ST7 44-46 43-44 42-42 42-43 45-46 43-45 43-44 43-44 42-43 43-45 286-296
36 Männer 36-45 ST8 47-48 45-47 43-45 44-46 47-48 46-48 45-46 45-48 44-45 46-48 297-310
37 Männer 36-45 ST9 49-49 48-49 46-49 47-49 49-49 49-49 47-49 49-49 46-49 49-49 311-343
38 Männer 46-55 ST1 7-21 7-17 7-12 7-20 7-27 7-20 7-26 7-19 7-26 7-24 49-187
39 Männer 46-55 ST2 22-28 18-25 13-17 21-25 28-30 21-26 27-29 20-26 27-28 25-28 188-203
40 Männer 46-55 ST3 29-33 26-29 18-25 26-29 31-35 27-33 30-33 27-30 29-32 29-33 204-222
41 Männer 46-55 ST4 34-37 30-34 26-31 30-34 36-41 34-38 34-37 31-35 33-35 34-37 223-247
42 Männer 46-55 ST5 38-41 35-40 32-37 35-39 42-42 39-41 38-41 36-40 36-38 38-41 248-270
43 Männer 46-55 ST6 42-43 41-42 38-41 40-41 43-46 42-43 42-42 41-42 39-41 42-42 271-286
44 Männer 46-55 ST7 44-45 43-46 42-42 42-43 47-47 44-46 43-44 43-43 42-43 43-45 287-297
45 Männer 46-55 ST8 46-48 47-48 43-47 44-48 48-48 47-48 45-46 44-46 44-44 46-48 298-309
46 Männer 46-55 ST9 49-49 49-49 48-49 49-49 49-49 49-49 47-49 47-49 45-49 49-49 310-343
47 Männer 56-65 ST1 7-20 7-11 7-15 7-19 7-27 7-27 7-27 7-23 7-24 7-26 49-185
48 Männer 56-65 ST2 21-25 12-18 16-22 20-27 28-33 28-32 28-32 24-27 25-30 27-30 186-214
49 Männer 56-65 ST3 26-31 19-27 23-28 28-30 34-39 33-36 33-35 28-28 31-33 31-34 215-236
50 Männer 56-65 ST4 32-35 28-28 29-34 31-37 40-41 37-40 36-38 29-33 34-37 35-38 237-255
51 Männer 56-65 ST5 36-39 29-37 35-38 38-41 42-44 41-42 39-41 34-38 38-39 39-41 256-272
52 Männer 56-65 ST6 40-42 38-41 39-41 42-43 45-46 43-43 42-42 39-41 40-42 42-44 273-286
53 Männer 56-65 ST7 43-43 42-44 42-43 44-47 47-47 44-46 43-44 42-42 43-43 45-46 287-298
54 Männer 56-65 ST8 44-46 45-48 44-47 48-48 48-48 47-48 45-46 43-44 44-45 47-48 299-311
55 Männer 56-65 ST9 47-49 49-49 48-49 49-49 49-49 49-49 47-49 45-49 46-49 49-49 312-343
56 Männer 66-75 ST1 7-19 7-15 7-19 7-25 7-27 7-26 7-28 7-15 7-25 7-27 49-192
57 Männer 66-75 ST2 20-23 16-21 20-26 26-27 28-29 27-30 29-31 16-20 26-28 28-31 193-215
58 Männer 66-75 ST3 24-28 22-27 27-31 28-30 30-36 31-34 32-35 21-25 29-32 32-34 216-232
59 Männer 66-75 ST4 29-34 28-31 32-35 31-34 37-40 35-38 36-37 26-28 33-35 35-38 233-246
60 Männer 66-75 ST5 35-37 32-35 36-37 35-40 41-42 39-41 38-40 29-32 36-38 39-41 247-261
61 Männer 66-75 ST6 38-41 36-39 38-41 41-43 43-45 42-43 41-42 33-37 39-41 42-43 262-276
62 Männer 66-75 ST7 42-43 40-42 42-42 44-47 46-47 44-46 43-44 38-41 42-43 44-45 277-289
63 Männer 66-75 ST8 44-45 43-46 43-45 48-48 48-48 47-48 45-46 42-42 44-45 46-48 290-297
64 Männer 66-75 ST9 46-49 47-49 46-49 49-49 49-49 49-49 47-49 43-49 46-49 49-49 298-343
65 Männer über 75 ST1 7-21 7-18 7-22 7-21 7-28 7-28 7-28 7-12 7-29 7-27 49-203
66 Männer über 75 ST2 22-26 19-24 23-31 22-27 29-33 29-31 29-32 13-19 30-30 28-28 204-214
67 Männer über 75 ST3 27-28 25-29 32-34 28-33 34-36 32-33 33-35 20-26 31-32 29-34 215-233
68 Männer über 75 ST4 29-33 30-33 35-37 34-37 37-41 34-36 36-39 27-28 33-35 35-37 234-249
69 Männer über 75 ST5 34-36 34-37 38-40 38-41 42-44 37-41 40-41 29-29 36-38 38-41 250-262
70 Männer über 75 ST6 37-40 38-43 41-42 42-45 45-47 42-43 42-43 30-33 39-42 42-44 263-280
71 Männer über 75 ST7 41-43 44-47 43-47 46-48 48-48 44-45 44-45 34-35 43-45 45-46 281-302
72 Männer über 75 ST8 44-45 48-49 48-48 49-49 49-49 46-48 46-47 36-41 46-48 47-48 303-305
73 Männer über 75 ST9 46-49 - 49-49 - - 49-49 48-49 42-49 49-49 49-49 306-343
74 Frauen 14-25 ST1 7-22 7-15 7-14 7-18 7-27 - 7-22 7-20 7-25 7-21 49-183
75 Frauen 14-25 ST2 23-27 16-26 15-21 19-25 28-29 7-27 23-28 21-25 26-28 22-25 184-208
76 Frauen 14-25 ST3 28-34 27-29 22-26 26-29 30-35 28-30 29-33 26-28 29-32 26-30 209-229
77 Frauen 14-25 ST4 35-40 30-35 27-30 30-34 36-39 31-37 34-38 29-33 33-36 31-35 230-250
78 Frauen 14-25 ST5 41-42 36-39 31-35 35-38 40-42 38-41 39-41 34-39 37-38 36-38 251-265
79 Frauen 14-25 ST6 43-45 40-42 36-38 39-42 43-45 42-45 42-42 40-42 39-41 39-41 266-281
80 Frauen 14-25 ST7 46-48 43-44 39-42 43-44 46-48 46-47 43-44 43-44 42-43 42-44 282-290
81 Frauen 14-25 ST8 49-49 45-47 43-44 45-48 49-49 48-48 45-46 45-46 44-46 45-46 291-300
82 Frauen 14-25 ST9 - 48-49 45-49 49-49 - 49-49 47-49 47-49 47-49 47-49 301-343
83 Frauen 26-35 ST1 7-23 7-16 7-17 7-19 7-24 7-28 7-25 7-23 7-25 7-22 49-188
84 Frauen 26-35 ST2 24-30 17-22 18-22 20-24 25-28 29-32 26-30 24-27 26-29 23-27 189-210
85 Frauen 26-35 ST3 31-35 23-28 23-26 25-28 29-35 33-37 31-35 28-31 30-33 28-31 211-236
86 Frauen 26-35 ST4 36-40 29-33 27-31 29-33 36-40 38-41 36-39 32-36 34-36 32-35 237-254
87 Frauen 26-35 ST5 41-42 34-38 32-36 34-38 41-42 42-42 40-41 37-40 37-39 36-39 255-270
88 Frauen 26-35 ST6 43-44 39-41 37-40 39-41 43-45 43-44 42-42 41-42 40-41 40-42 271-285
89 Frauen 26-35 ST7 45-47 42-44 41-42 42-42 46-47 45-47 43-44 43-44 42-43 43-45 286-298
90 Frauen 26-35 ST8 48-48 45-48 43-46 43-46 48-48 48-48 45-47 45-48 44-45 46-47 299-308
91 Frauen 26-35 ST9 49-49 49-49 47-49 47-49 49-49 49-49 48-49 49-49 46-49 48-49 309-343
92 Frauen 36-45 ST1 7-24 7-19 7-14 7-19 7-21 7-27 7-26 7-21 7-25 7-24 49-187
93 Frauen 36-45 ST2 25-29 20-25 15-21 20-25 22-28 28-30 27-30 22-27 26-29 25-28 188-211
94 Frauen 36-45 ST3 30-34 26-28 22-28 26-29 29-33 31-35 31-34 28-31 30-33 29-34 212-235
95 Frauen 36-45 ST4 35-38 29-34 29-34 30-34 34-40 36-39 35-38 32-35 34-36 35-37 236-255
96 Frauen 36-45 ST5 39-41 35-39 35-38 35-38 41-42 40-41 39-41 36-40 37-39 38-41 256-272
97 Frauen 36-45 ST6 42-43 40-41 39-41 39-41 43-44 42-44 42-42 41-42 40-41 42-43 273-284
98 Frauen 36-45 ST7 44-45 42-43 42-42 42-43 45-46 45-46 43-43 43-43 42-43 44-45 285-296
99 Frauen 36-45 ST8 46-48 44-47 43-45 44-47 47-48 47-48 44-46 44-46 44-45 46-48 297-313
100 Frauen 36-45 ST9 49-49 48-49 46-49 48-49 49-49 49-49 47-49 47-49 46-49 49-49 314-343
101 Frauen 46-55 ST1 7-21 7-11 7-13 7-19 7-21 7-27 7-25 7-19 7-24 7-26 49-186
102 Frauen 46-55 ST2 22-28 12-24 14-21 20-26 22-27 28-31 26-30 20-25 25-29 27-29 187-211
103 Frauen 46-55 ST3 29-33 25-28 22-29 27-29 28-34 32-35 31-34 26-28 30-33 30-34 212-231
104 Frauen 46-55 ST4 34-37 29-34 30-34 30-34 35-38 36-38 35-37 29-32 34-36 35-37 232-249
105 Frauen 46-55 ST5 38-41 35-39 35-38 35-38 39-41 39-41 38-41 33-37 37-39 38-41 250-267
106 Frauen 46-55 ST6 42-42 40-42 39-41 39-42 42-44 42-43 42-42 38-41 40-41 42-44 268-287
107 Frauen 46-55 ST7 43-44 43-44 42-43 43-45 45-47 44-47 43-45 42-42 42-43 45-47 288-303
108 Frauen 46-55 ST8 45-47 45-48 44-48 46-48 48-48 48-48 46-47 43-45 44-45 48-48 304-313
109 Frauen 46-55 ST9 48-49 49-49 49-49 49-49 49-49 49-49 48-49 46-49 46-49 49-49 314-343
110 Frauen 56-65 ST1 7-20 7-12 7-17 7-24 7-23 7-27 7-26 7-19 7-24 7-25 49-192
111 Frauen 56-65 ST2 21-26 13-26 18-24 25-27 24-27 28-29 27-30 20-21 25-29 26-28 193-207
112 Frauen 56-65 ST3 27-30 27-27 25-28 28-30 28-28 30-34 31-34 22-27 30-33 29-34 208-233
113 Frauen 56-65 ST4 31-35 28-28 29-34 31-35 29-37 35-38 35-38 28-29 34-37 35-39 234-249
114 Frauen 56-65 ST5 36-39 29-32 35-37 36-40 38-41 39-41 39-41 30-34 38-39 40-41 250-269
115 Frauen 56-65 ST6 40-42 33-40 38-41 41-43 42-43 42-44 42-42 35-39 40-42 42-44 270-280
116 Frauen 56-65 ST7 43-44 41-42 42-42 44-46 44-46 45-46 43-44 40-41 43-44 45-47 281-292
117 Frauen 56-65 ST8 45-46 43-47 43-45 47-48 47-48 47-48 45-46 42-42 45-47 48-48 293-308
118 Frauen 56-65 ST9 47-49 48-49 46-49 49-49 49-49 49-49 47-49 43-49 48-49 49-49 309-343
119 Frauen 66-75 ST1 7-20 7-9 7-18 7-21 7-25 7-27 7-26 7-19 7-25 7-24 49-190
120 Frauen 66-75 ST2 21-23 10-17 19-23 22-27 26-27 28-28 27-29 20-20 26-28 25-30 191-206
121 Frauen 66-75 ST3 24-28 18-24 24-29 28-31 28-28 29-33 30-33 21-24 29-32 31-35 207-226
122 Frauen 66-75 ST4 29-34 25-27 30-34 32-35 29-33 34-39 34-37 25-27 33-37 36-39 227-249
123 Frauen 66-75 ST5 35-37 28-28 35-38 36-41 34-40 40-41 38-40 28-29 38-40 40-41 250-262
124 Frauen 66-75 ST6 38-41 29-31 39-41 42-44 41-45 42-43 41-42 30-33 41-42 42-43 263-271
125 Frauen 66-75 ST7 42-43 32-42 42-42 45-48 46-48 44-45 43-43 34-39 43-44 44-46 272-290
126 Frauen 66-75 ST8 44-47 43-47 43-46 49-49 49-49 46-48 44-46 40-43 45-48 47-48 291-296
127 Frauen 66-75 ST9 48-49 48-49 47-49 - - 49-49 47-49 44-49 49-49 49-49 297-343
128 Frauen über 75 ST1 7-14 7-9 7-23 7-25 7-24 7-27 7-26 7-9 7-26 7-26 49-188
129 Frauen über 75 ST2 15-19 10-17 24-27 26-28 25-26 28-28 27-27 10-21 27-27 27-30 189-202
130 Frauen über 75 ST3 20-25 18-22 28-31 29-32 27-27 29-34 28-32 22-26 28-31 31-34 203-214
131 Frauen über 75 ST4 26-29 23-27 32-35 33-35 28-29 35-37 33-35 27-27 32-37 35-39 215-246
132 Frauen über 75 ST5 30-34 28-31 36-39 36-41 30-33 38-41 36-40 28-28 38-40 40-42 247-257
133 Frauen über 75 ST6 35-37 32-35 40-41 42-44 34-43 42-43 41-42 29-29 41-43 43-44 258-276
134 Frauen über 75 ST7 38-44 36-37 42-43 45-48 44-46 44-47 43-46 30-31 44-46 45-47 277-292
135 Frauen über 75 ST8 45-47 38-40 44-48 49-49 47-48 48-48 47-48 32-41 47-48 48-48 293-306
136 Frauen über 75 ST9 48-49 41-49 49-49 - 49-49 49-49 49-49 42-49 49-49 49-49 307-343

3067
FLZ/renv.lock Normal file

File diff suppressed because it is too large Load diff

20
FLZ/setup_renv.R Normal file
View file

@ -0,0 +1,20 @@
# Einmalig ausfuehren, bevor die App zum ersten Mal gestartet wird.
# Initialisiert renv und installiert alle benoetigten Pakete.
#
# 'formr' wird nicht von app.R selbst benoetigt (die App importiert keine
# API-Keys/DB-Zugriffe direkt), sondern vom extern gepflegten, gesourcten
# Download-Skript (../get_data_flz.R) - analog zu DBI/RSQLite, die vom
# gesourcten Pseudonym-Skript gebraucht werden. 'formr' liegt nicht auf
# CRAN, daher Installation ueber remotes::install_github().
renv::init()
pkgs = c("shiny", "dplyr", "ggplot2", "haven", "officer", "DBI", "RSQLite")
install.packages(pkgs)
if (!requireNamespace("remotes", quietly = TRUE)) install.packages("remotes")
remotes::install_github("rubenarslan/formr")
renv::snapshot()
message("Setup abgeschlossen. App starten mit: shiny::runApp()")