Groups people who behave alike, so that a model can be fitted per subgroup rather than pooling everyone or fitting everyone separately.
Usage
find_subgroups(
data,
y,
x,
id,
method = c("effect_clustering", "error_clustering", "repeated_split", "model_tree",
"mixture_regression", "random_partition"),
k = 2L,
reps = 50L,
moderators = NULL,
time = NULL,
k_max = 6L,
...
)Arguments
- data
Data frame.
- y
Outcome column name.
- x
Predictors (any
fit_lm()selector).- id
Person/unit ID column.
- method
Discovery method.
- k
Number of subgroups, or
"auto"to choose it by stability.- reps
Resamples used for the stability score.
- moderators
Person-level column(s) to split on. Required by
method = "model_tree", ignored otherwise. Must be constant within person.- time
Optional ordering column.
- k_max
Largest
kconsidered whenk = "auto".- ...
Ignored.
Value
An idiographic_groups object. Use groups() for the tidy table.
Details
Methods:
effect_clusteringCluster people by their person-specific slopes. People whose predictors act the same way land together.
error_clusteringCluster people by how a pooled model fails them (error size and direction). Finds who the pooled model does not serve.
repeated_splitLike
effect_clustering, but slopes are recomputed on repeated resamples, so unstable people are exposed.model_treeSplit people on person-level
moderators(age, condition, baseline score) to reduce prediction error. The only method that says why people differ, in terms of variables you measured.mixture_regressionA finite mixture of regressions fitted by EM, with the person as the mixing unit: every row a person contributes counts towards that person's likelihood under each component, so people are assigned whole. Unlike
effect_clusteringit does not need a separate regression per person, so it can place people with too few occasions to support one.$mixtureholds the component regressions and the posterior probabilities, andgroups()gains aposteriorcolumn – how sure the model is of each assignment, which is a stronger statement than how often a partition reproduces. Matchesflexmix::flexmix(y ~ x | id)to the reported precision on log-likelihood, BIC and assignment.random_partitionRandom labels. A null baseline: compare its stability against a real method to see whether structure exists.
These methods always return subgroups, including when there are none.
Call test_subgroups() first, or use k = "auto", which is allowed to answer
"one population".
Stability is a consensus score: each person is repeatedly re-clustered on resampled rows, and stability is how often they land with the same companions. It measures whether a partition is reproducible, not whether it is real. In simulation, data containing no subgroups at all scored 0.89-0.97 – because slicing a single smooth cloud of coefficients in half is highly repeatable. Do not read a high stability as evidence that the groups exist.
With k = "auto" the number of subgroups is chosen by test_subgroups(), a
Gaussian mixture on the person coefficients selected by BIC over both the
number of components and the covariance structure. It may return one, in
which case a warning is raised and the partition should not be trusted. See
$selection for the BIC table and $shape for the skewness diagnostic.
method = "mixture_regression" defers to the same test rather than to its
own BIC, and the reason is worth knowing. On 30 simulated panels containing
no subgroups – one population whose slopes merely varied continuously –
the mixture's BIC chose more than one component 30 times out of 30, while
test_subgroups() answered "one population" 30 times out of 30 and still
recovered two real classes when they were present. A mixture of regressions
fits a continuum of slopes better with two components than with one, and its
BIC has no device to tell that apart from genuine classes. The mixture's own
BIC table is still reported in $mixture_bic, for comparison with a
flexmix-style workflow – it simply does not get to choose.
Examples
g <- find_subgroups(srl, y = "effort", x = "efficacy:monitoring",
id = "name", k = 2, reps = 10)
groups(g)
#> subject subgroup method stability n_assignments
#> 1 Aisha g2 effect_clustering 0.8411765 10
#> 2 Alice g2 effect_clustering 0.9117647 10
#> 3 Anika g1 effect_clustering 0.5823529 10
#> 4 Astrid g1 effect_clustering 0.7941176 10
#> 5 Bjorn g1 effect_clustering 0.4882353 10
#> 6 Bob g2 effect_clustering 0.9117647 10
#> 7 Charlie g1 effect_clustering 0.8647059 10
#> 8 Diana g1 effect_clustering 0.8647059 10
#> 9 Erik g1 effect_clustering 0.8647059 10
#> 10 Eve g2 effect_clustering 0.9117647 10
#> 11 Fatima g1 effect_clustering 0.8647059 10
#> 12 Frank g1 effect_clustering 0.8647059 10
#> 13 Freja g1 effect_clustering 0.8647059 10
#> 14 Grace g1 effect_clustering 0.8647059 10
#> 15 Hassan g2 effect_clustering 0.8411765 10
#> 16 Heidi g1 effect_clustering 0.8058824 10
#> 17 Hiroshi g2 effect_clustering 0.4764706 10
#> 18 Ingrid g1 effect_clustering 0.4764706 10
#> 19 Ivan g2 effect_clustering 0.9117647 10
#> 20 Judy g2 effect_clustering 0.8294118 10
#> 21 Karin g1 effect_clustering 0.3470588 10
#> 22 Lars g2 effect_clustering 0.9117647 10
#> 23 Layla g2 effect_clustering 0.9117647 10
#> 24 Li g2 effect_clustering 0.9117647 10
#> 25 Liv g2 effect_clustering 0.9117647 10
#> 26 Mei g2 effect_clustering 0.7705882 10
#> 27 Nils g1 effect_clustering 0.8647059 10
#> 28 Noor g2 effect_clustering 0.5117647 10
#> 29 Omar g2 effect_clustering 0.9117647 10
#> 30 Ravi g1 effect_clustering 0.8647059 10
#> 31 Saanvi g1 effect_clustering 0.8647059 10
#> 32 Sakura g2 effect_clustering 0.9117647 10
#> 33 Sven g2 effect_clustering 0.9117647 10
#> 34 Takumi g1 effect_clustering 0.8647059 10
#> 35 Yuki g1 effect_clustering 0.8647059 10
#> 36 Zain g2 effect_clustering 0.9117647 10
# Let the data choose how many subgroups there are.
auto <- find_subgroups(srl, y = "effort", x = "efficacy:monitoring",
id = "name", k = "auto", k_max = 4, reps = 10)
#> Warning: No subgroups detected: one population fits these people best. Any partition returned below is not supported by the data.
auto$selection
#> k model loglik npar bic selected
#> 1 1 EII -202.2988 5 422.5153 TRUE
#> 2 1 VII -202.2988 5 422.5153 FALSE
#> 3 2 EII -195.1972 10 426.2296 FALSE
#> 4 2 VII -194.5701 11 428.5589 FALSE
#> 5 2 EEI -191.4409 13 429.4675 FALSE
#> 6 1 EEE -191.2969 14 432.7631 FALSE
#> 7 1 VVV -191.2969 14 432.7631 FALSE
#> 8 1 EEI -202.2988 8 433.2658 FALSE
#> 9 1 VVI -202.2988 8 433.2658 FALSE
#> 10 3 VII -186.3938 17 433.7074 FALSE
#> 11 2 VVV -165.3181 29 434.5582 FALSE
#> 12 3 EII -191.2184 15 436.1897 FALSE
#> 13 2 EEE -185.1661 19 438.4190 FALSE
#> 14 2 VVI -189.2301 17 439.3800 FALSE
#> 15 3 EEI -187.4943 18 439.4919 FALSE
#> 16 3 EEE -179.4884 24 444.9812 FALSE
#> 17 4 VII -182.2114 23 446.8438 FALSE
#> 18 4 EII -189.0430 20 449.7565 FALSE
#> 19 4 VVV -120.4172 59 452.2620 FALSE
#> 20 3 VVI -179.7337 26 452.6388 FALSE
#> 21 4 EEI -185.1333 23 452.6875 FALSE
#> 22 3 VVV -149.2422 44 456.1591 FALSE
#> 23 4 EEE -176.5275 29 456.9771 FALSE
#> 24 4 VVI -173.6042 35 472.6316 FALSE