Tutorials › Generalized Linear Mixed Models (GLMM) › Plotting Observed Outcomes Across Clusters

Software and Case Studies · Tutorial 667 of 698

Plotting Observed Outcomes Across Clusters

Build clear cluster-level plots that show observed outcomes alongside the amount of information behind each cluster.

Intermediate 10 min read

What You'll Learn

  • Calculate and plot an observed binary proportion for each cluster.
  • Display cluster denominators so unequal cluster sizes remain visible.
  • Calculate count rates using a suitable exposure denominator.
  • Choose point, label, and axis mappings that communicate cluster-level data clearly.
  • Recognize why descriptive plots do not establish adjusted effects or model assumptions.
  • Check cluster data for invalid denominators, missing clusters, and misleading scales.

Why Plot Outcomes by Cluster?

Before presenting estimates from a generalized linear mixed model, it is useful to show what was actually observed in each cluster. A plot can reveal whether clusters differ in size, whether observed outcomes vary substantially, and whether a few clusters have unusual values. It also helps readers see the structure to which a model will be applied. The display is descriptive: it does not adjust for predictors, estimate random effects, or establish that a cluster caused an outcome difference.

For binary data, the natural cluster-level summary is the observed proportion of outcomes coded 1. For counts, a count rate is meaningful only when its exposure denominator is stated and appropriate. In both cases, the size of a cluster matters: a proportion based on 5 observations is less stable than the same proportion based on 500, and a count based on more exposure will often be larger even if its rate is unchanged.

Definition: Let \(j=1,\ldots,J\) index clusters. For binary outcomes, let \(n_j\) be the number of eligible observations in cluster \(j\), and let \(S_j\) be the number with outcome 1. The observed proportion is \(\hat{p}_j=S_j/n_j\), defined when \(n_j>0\). For count outcomes, let \(C_j\) be the observed count and \(E_j>0\) its relevant exposure. The observed rate is \(C_j/E_j\), often rescaled to a readable unit such as events per 100 person-months.

Each plotted point should represent a clearly defined cluster-level quantity. The horizontal position can identify clusters, and the vertical position can show \(\hat{p}_j\) or \(C_j/E_j\). Show \(n_j\) or \(E_j\) as well, either with a text label, a point-size mapping, or both. Labels are often easiest to interpret; size encodings are compact but require a visible legend and can be hard to compare precisely.

Plotting Binary Proportions

A binary proportion is bounded between 0 and 1. Use a proportion scale with a clear axis label, or a percentage scale from 0% to 100%; do not switch between the two without labeling the units. A dot plot is usually preferable to a bar chart for cluster comparisons because the plotted value is directly visible and the display does not imply a continuous amount of filled area. Ordering clusters by observed proportion can make patterns easier to scan, but retaining a meaningful order, such as site order or region, may be preferable when that order is part of the design.

For a binary plot, cluster size should be apparent. One practical design is to label each point with its denominator, for example “n = 10,” or to map point size to \(n_j\) while also printing the denominator. If labels overlap, use a separate table or a caption that reports the cluster sizes; omitting sizes altogether can make a small, noisy cluster look as informative as a large one.

Worked Example: Clinic Proportions and Denominators

Suppose a hypothetical dataset records whether each eligible patient experienced a binary outcome at four clinics. The cluster summaries are as follows.

ClinicOutcome 1, \(S_j\)Patients, \(n_j\)Observed proportion, \(\hat{p}_j\)
A2100.200
B9150.600
C12200.600
D150.200

For Clinic A, \(\hat{p}_A=2/10=0.200\); for Clinic B, \(\hat{p}_B=9/15=0.600\); for Clinic C, \(\hat{p}_C=12/20=0.600\); and for Clinic D, \(\hat{p}_D=1/5=0.200\). Plot the four proportions on the vertical axis and identify each clinic on the horizontal axis. Label the points with \(n=10\), \(n=15\), \(n=20\), and \(n=5\), respectively. The display then shows that A and D have the same observed proportion, but D’s value is based on fewer patients.

In R, after creating a summary dataset with one row per clinic and columns named clinic, proportion, and n, a point plot can be specified as `ggplot(summary, aes(x = reorder(clinic, proportion), y = proportion)) + geom_point(aes(size = n)) + geom_text(aes(label = paste0("n=", n)), nudge_y = 0.04) + scale_size_area(max_size = 8) + coord_flip() + labs(x = "Clinic", y = "Observed proportion", size = "Patients")`. The point-size legend and direct labels both make the denominator visible; the labels may be omitted if they overlap, provided the denominators remain available in an adjacent table or caption.

The pooled proportion is not the unweighted mean of the four clinic proportions. It is the total number of outcome-1 observations divided by the total number of patients:

$$ \hat{p}_{\mathrm{pooled}} =\frac{\sum_j S_j}{\sum_j n_j} =\frac{2+9+12+1}{10+15+20+5} =\frac{24}{50} =0.480. $$

By contrast, the unweighted mean of the four cluster proportions is \((0.200+0.600+0.600+0.200)/4=0.400\). These summaries answer different descriptive questions: the pooled value gives each patient equal weight, whereas the unweighted mean gives each clinic equal weight. Neither should be mistaken for a covariate-adjusted GLMM estimate.

Plotting Count Rates

A count is not a rate. When clusters differ in the amount of time, population, area, or other exposure over which events could occur, plotting raw counts alone can be misleading. First define the count and its exposure in the study context, then calculate a rate with an explicit scale. For example, \(C_j/E_j\) is a rate per person-month if \(C_j\) counts events and \(E_j\) is measured in person-months. Multiplying by 100 expresses the same rate per 100 person-months; it does not change the underlying comparison.

The display should name both the outcome and the rate unit. Show \(E_j\) in a point label or a size mapping, just as \(n_j\) is shown for binary proportions. A zero count with positive exposure has rate zero and belongs on the plot. A cluster with zero exposure has no defined rate and should not be plotted as a zero-rate cluster.

Worked Example: Event Rates with Unequal Exposure

Consider hypothetical event counts from four service units. Exposure is measured in person-months, and the requested display is events per 100 person-months.

UnitEvents, \(C_j\)Exposure, \(E_j\)Rate per 100 person-months
A81008.00
B72528.0
C0500.00
D122006.00

For Unit A, \(100(8/100)=8.00\) events per 100 person-months. For Unit B, \(100(7/25)=28.0\); for Unit C, \(100(0/50)=0\); and for Unit D, \(100(12/200)=6.00\). Plot these four rates against unit, label the vertical axis “Events per 100 person-months,” and show the exposures of 100, 25, 50, and 200 person-months. Unit B has fewer events than Unit D but a larger observed rate because its exposure is much smaller.

A suitable R display uses the calculated rate as the vertical variable and labels or maps point size to exposure, for example `ggplot(summary, aes(x = unit, y = rate_per_100)) + geom_point(aes(size = exposure)) + geom_text(aes(label = paste0("E=", exposure)), nudge_y = 1) + scale_size_area(max_size = 8) + labs(x = "Unit", y = "Events per 100 person-months", size = "Person-months")`. The rate calculation must use the exposure unit actually recorded; relabeling the axis cannot repair an incorrectly constructed denominator.

For context, the combined descriptive rate is \(100(27/375)=7.20\) events per 100 person-months, because the total is 27 events over 375 person-months. This pooled rate weights units according to exposure. It is not the simple average of the four displayed rates, which is \((8+28+0+6)/4=10.5\) events per 100 person-months, and neither number adjusts for differences in the units’ composition or other predictors.

A Short Justification: Why Cluster Size Belongs in the Display

For independent binary observations within a cluster, each with the same probability \(p_j\), the count \(S_j\) has variance \(n_jp_j(1-p_j)\). Since \(\hat{p}_j=S_j/n_j\), dividing the count variance by \(n_j^2\) gives:

$$ \operatorname{Var}(\hat{p}_j) =\operatorname{Var}\left(\frac{S_j}{n_j}\right) =\frac{n_jp_j(1-p_j)}{n_j^2} =\frac{p_j(1-p_j)}{n_j}. $$

Thus, under those assumptions, larger \(n_j\) generally means less sampling variability in the observed proportion. This justifies displaying denominators; it does not justify treating this variance formula as a valid uncertainty calculation in every GLMM dataset. Within-cluster dependence, varying probabilities within a cluster, and other features of the design can invalidate the simple binomial calculation. A plot of raw proportions remains a descriptive display, but intervals or tests require assumptions suited to the actual data structure.

Construction Checks and Common Pitfalls

Before plotting, verify that the plotted summaries match the analysis dataset and that each cluster is represented once. In a binary dataset, check that the outcome coding is consistent, that \(S_j\) counts only eligible outcomes coded 1, and that \(n_j\) is the matching number of eligible observations. In a count dataset, check that \(C_j\) and \(E_j\) cover the same cluster and time period and that every positive rate has a positive, meaningful exposure. Missing clusters should not disappear silently: determine whether they have no eligible observations, missing outcome records, or a data-processing error.

  • Plotting counts when exposure differs. A larger count can simply reflect more time at risk or a larger population. Plot rates with clearly defined exposure when a rate is the relevant summary.
  • Hiding denominators. Two equal proportions can have very different precision when their denominators differ. Add labels, point-size encoding, or an accompanying table.
  • Turning no data into zero. If \(n_j=0\), \(\hat{p}_j\) is undefined; if \(E_j=0\), \(C_j/E_j\) is undefined. Do not place either as a zero-valued point.
  • Reading raw differences as adjusted effects. Cluster proportions and rates do not control for case mix, predictors, or dependence. A visible difference is descriptive, not evidence that the cluster itself caused the difference.
  • Over-interpreting tiny clusters. A proportion of 0 or 1 may occur in a small cluster by chance. Show its denominator and avoid presenting an extreme point as a stable cluster characteristic.

A proportion dot plot is often clearest for binary outcomes, while a rate dot plot is appropriate for counts with varying exposure. A bar chart can show the same summaries, but bars use more visual area and may obscure close values. A table reports exact values and denominators but makes patterns across many clusters harder to see. Model-based fitted values or estimates answer adjusted or model-dependent questions; they can supplement a raw-data display, but they should not be substituted for it when the aim is to show observed outcomes.

Key takeaway: Plot one observed proportion or exposure-based rate per cluster, make the denominator visible, and label the outcome scale and units. Read the figure as a description of the data—not as an adjusted comparison or a test of a GLMM.

Check Your Understanding

Work through the questions, then compare your reasoning with the solutions below.

  1. Cluster P has 6 outcomes coded 1 among 12 observations, and Cluster Q has 15 among 30. What proportions should be plotted, and what else should the display show?
  2. A unit records 9 events over 30 person-months. Calculate its rate per 100 person-months and state the axis label.
  3. A cluster has no eligible observations. Should its observed binary proportion be plotted as zero? Explain.
  4. Why can the unweighted mean of cluster proportions differ from the pooled proportion?

Solutions. (1) P has \(6/12=0.500\), and Q has \(15/30=0.500\). Plot both proportions and show denominators 12 and 30, because equal observed values do not mean equal cluster sizes. (2) The rate is \(100(9/30)=30.0\) events per 100 person-months; use an axis label such as “Events per 100 person-months.” (3) No. With \(n_j=0\), the proportion is undefined because its denominator is zero; represent the cluster’s lack of eligible observations explicitly rather than assigning a zero outcome. (4) The unweighted mean gives every cluster equal weight, whereas the pooled proportion is \(\sum_j S_j/\sum_j n_j\) and weights clusters by their observation counts. They coincide only in some datasets, such as when all cluster sizes are equal.

Clinical Biostats