Reads the participant workbook, binds its per-course sheets, applies
sdt_participant_dictionary() and returns one row per participant record
with the raw and the normalised columns side by side.
Usage
sdt_read_participants(
path,
dictionary = sdt_participant_dictionary(),
sheets = NULL,
verbose = TRUE
)Arguments
- path
Path to the participant workbook (
.xlsx). Read-only; nothing is written to it or beside it.- dictionary
A
sdt_participant_dictionary.- sheets
Optional character vector of per-course sheet names to restrict to.
NULL, the default, reads every sheet named in the workbook'sCourse_Index.- verbose
Report row counts, neutralised leaks and per-covariate missingness while reading.
Value
A sdt_participants object: a tibble::tibble() subclass, one row
per participant record, with attributes course_index (one row per
course, including the empty ones), dictionary and meta.
What this data can and cannot do
The register links a person to a course. It carries no group, team or
"Gruppe" column, so a participant cannot be placed in group A rather than
group B. Every group inside one course therefore shares the same
composition row. In the behaviour model
y ~ card + (1 | block) + (1 | group) these covariates are block-level:
they can compete with the session random effect, and can never explain
the team random effect, which has no composition variance to spend.
Treat any composition analysis as a between-course regression on as many
points as there are courses.
Missingness
Courses with no linked participants are kept, not dropped: the
course_index attribute carries every course in the workbook with its
n_participants and has_participants, so a caller sees the empty courses
rather than inferring them from an absence.
Rows the extractor wrote a diagnostic into instead of an answer are
detected and neutralised to NA before anything is normalised, and a row
with nothing but such a diagnostic is a course placeholder rather than a
person: it is removed from the participant rows and counted in
course_index$n_placeholder_rows.
Two logical column families record what happened to every raw field:
.missing_<field>— the information is not available. Forfunktionthis includes the declared non-answer "Nichts angegeben", which is missing information rather than a grade; forweiterbildungsjahreit includes unparseable free text such as","..imputed_<field>— the normalised value was filled rather than observed. Onlytitelhas a participant-level fill rule by default (an empty title box becomesnone, seesdt_participant_dictionary()); the rest are filled, if at all, at course level bysdt_course_composition(). An imputed value is never indistinguishable from an observed one.
See also
sdt_course_composition() to aggregate to course level,
sdt_participant_summary() for descriptives that state their
denominators.
Examples
if (FALSE) { # \dontrun{
p <- sdt_read_participants("TDSC_course_participant_relations.xlsx")
p
attr(p, "course_index")
sdt_course_composition(p)
} # }