Grouped summaries are central to clinical research monitoring. A data manager may need to summarize enrollment by site, missing values by visit, adverse events by severity and related ness, protocol deviations by category, and query burden by status. Grouped summaries are created by defining one or more grouping variables and then calculating counts or statistics within those groups.
The following code summarizes enrollment by site:

site_enrollment <- prepared_data |>
group_by(site) |>
summarise(
participants_enrolled = n_distinct(participant_id),
.groups = “drop”
) |>
arrange(desc(participants_enrolled))
site_enrollment

This uses n_distinct(participant_id) rather than n() because enrollment should count
participants, not necessarily rows. If the dataset is participant-level, the two may be the same.
If the dataset has repeated visits, n() may overcount participants. This is a recurring theme: denominators must match the question.
To summarize missing data by site:

site_missing_summary <- prepared_data |>
group_by(site) |>
summarise(
n_participants = n_distinct(participant_id),
missing_consent_date = sum(is.na(consent_date)),
missing_day28_outcome = sum(is.na(day28_outcome)),
percent_missing_day28 = round(100 * missing_day28_outcome / n_participants, 1),
.groups = “drop”
)
site_missing_summary

 

This table can support operationalfollow-up. It should be interpreted with recruitment timing. If many participants at a site are newly enrolled, day 28 outcomes may not yet be due. A better denominator may include only participants whose day 28 assessment is due:

site_due_outcome_summary <- prepared_data |>
filter(day28_due_date <= Sys.Date()) |>
group_by(site) |>
summarise(
outcomes_due = n_distinct(participant_id),
outcomes_missing = sum(is.na(day28_outcome)),
percent_missing = round(100 * outcomes_missing / outcomes_due, 1),
.groups = “drop”
)

This demonstrates the importance of clinically meaningful denominators. A simple missing ness percentage can be misleading if the timing of expected data is ignored.
Grouped summaries can also support safety review:

adverse_event_summary <- ae_data |>
group_by(site, ae_severity) |>
summarise(
n_events = n(),
n_participants = n_distinct(participant_id),
.groups = “drop”
)

For adverse events, event counts and participant counts answer different questions. One participant may have several adverse events. A table should make clear whether it counts events or participants. Safety summaries require particular care and should follow the safety monitoring plan or statistical analysis plan.

 

Grouped summary Grouping variable Count or statistic Interpretation issue
Enrollment by site Site Distinct participants Site activation dates may differ
Missing outcomes by site Site Missing among due outcomes Denominator should exclude not-yet-due records
Queries by status Site and query status Query count Open queries may reflect recent enrollment
Adverse events by severity Severity and site Event count and participant count Events and participants are different units
Visit completion Visit and site Completed visits / expected visits Expected visits depend on schedule and eligibility

Grouped summaries are often the foundation of dashboards and automated reports. Before visualizing them, however, the table itself should be correct and interpretable.