From Raw Panel Data to Person-Specific Conclusions
Source:vignettes/unified-workflow.Rmd
unified-workflow.Rmdidiographic treats the person as the primary analytical
unit. This vignette shows the common path from inspecting repeated
observations to comparing person-specific conclusions. Network methods
use the same person-by-time data contract and are covered in the
method-specific vignettes.
Inspect the panel
The bundled srl data contain daily observations nested
within learners.
vars <- c("efficacy", "monitoring", "effort")
describe_persons(srl, id = "name", vars = vars, time = "day", n = 6)
#> PERSON DESCRIPTIVES
#> Grouping name
#> Time day
#> People 6
#> Variables 1
#>
#> subject variable n miss mean median sd min max rmssd autocor span gap_median gap_max
#> -----------------------------------------------------------------------------------------------------------------------------------
#> Aisha efficacy 156 0 56.919 61.765 21.034 0.000 100.000 26.881 0.169 155.000 1.000 1.000
#> Alice efficacy 156 0 35.761 36.364 20.614 0.000 100.000 28.790 0.024 155.000 1.000 1.000
#> Anika efficacy 156 0 50.099 47.692 19.373 0.000 100.000 28.656 -0.124 155.000 1.000 1.000
#> Astrid efficacy 156 0 72.401 78.378 20.078 10.811 100.000 28.496 -0.008 155.000 1.000 1.000
#> Bjorn efficacy 156 0 52.707 51.852 21.803 3.704 100.000 30.443 0.023 155.000 1.000 1.000
#> Bob efficacy 154 2 78.219 77.108 16.717 0.000 100.000 23.209 0.028 155.000 1.000 1.000
#>
#> sd = overall spread; rmssd = occasion-to-occasion change
#> autocor = lag-1 carry-over (inertia)
correlate_persons(srl, id = "name", vars = vars, n = 6)
#> PERSON-SPECIFIC CORRELATIONS
#> Grouping name
#> People 2
#> Pairs 3
#>
#> subject x y n r 95% CI p
#> ------------------------------------------------------------------------------
#> Aisha efficacy monitoring 156 0.394 [0.25, 0.52] < 1e-04
#> Aisha efficacy effort 156 0.352 [0.21, 0.48] < 1e-04
#> Aisha monitoring effort 156 0.284 [0.13, 0.42] 0.000325
#> Alice efficacy monitoring 156 -0.231 [-0.37, -0.08] 0.003736
#> Alice efficacy effort 156 0.491 [0.36, 0.60] < 1e-04
#> Alice monitoring effort 156 -0.352 [-0.48, -0.21] < 1e-04
variance_components(srl, id = "name", vars = vars)
#> VARIANCE COMPONENTS
#> Grouping name
#> Method anova
#>
#> Within Between ICC Reliability
#> --------------------------------------------------------
#> efficacy 472.5379 249.7267 0.346 0.988
#> monitoring 467.1183 437.6607 0.484 0.993
#> effort 522.5017 207.7688 0.285 0.984
#>
#> ICC share of variance lying BETWEEN groups
#> Reliability precision of each group's own meanThe descriptive layer reports each person’s usable observations, missingness, variation, serial dependence, and sampling gaps. Inspecting these quantities before fitting helps distinguish a model failure from a panel that cannot identify the requested person-specific effect.
Prepare within-person variables
preprocess_panel() transforms columns without crossing
person boundaries. The example adds a person-centred predictor and its
previous-occasion value.
panel <- preprocess_panel(
srl,
id = "name",
time = "day",
vars = c("efficacy", "monitoring"),
center = "person",
lag = 1
)Use preprocess() instead when the goal is the
established network-readiness audit (stationarity, compliance, variance,
and related diagnostics).
Compare pooled and individual estimates
The default scope fits a pooled comparison and one model per person. Ordered hold-out validation uses the final observations of each person as test rows.
fit <- fit_lm(
panel,
y = "effort",
x = c("efficacy", "monitoring", "efficacy_lag1"),
id = "name",
time = "day",
scope = "both",
min_train = 30
)
metrics(fit, overall = TRUE)
#> scope model estimator subject subgroup n rmse mae bias
#> 1 pooled lm native .overall .all 1150 24.45330 20.48970 0.5741532
#> 2 individual lm native .overall .all 1150 18.79467 14.55597 0.3911686
#> r_squared
#> 1 0.1714338
#> 2 0.5105349
coefs(fit, scope = "individual", n = 8)
#> scope model estimator subject subgroup term estimate
#> 1 individual lm native Aisha .none (Intercept) 77.325111113
#> 2 individual lm native Aisha .none efficacy 0.211722912
#> 3 individual lm native Aisha .none monitoring 0.154777528
#> 4 individual lm native Aisha .none efficacy_lag1 -0.002918768
#> 5 individual lm native Alice .none (Intercept) 60.422756642
#> 6 individual lm native Alice .none efficacy 0.456545348
#> 7 individual lm native Alice .none monitoring -0.327781383
#> 8 individual lm native Alice .none efficacy_lag1 -0.108543860
#> std_error statistic p_value
#> 1 1.58108831 48.90625681 1.201203e-80
#> 2 0.08470843 2.49943131 1.380211e-02
#> 3 0.06946865 2.22801977 2.775848e-02
#> 4 0.07567714 -0.03856869 9.692989e-01
#> 5 1.55462437 38.86646687 1.801465e-69
#> 6 0.07646448 5.97068534 2.509109e-08
#> 7 0.08063487 -4.06500768 8.657107e-05
#> 8 0.07428774 -1.46112756 1.466159e-01individuals(fit), pooled(fit),
person(fit, id), and overall(fit) create
focused views without changing the underlying estimates.
Separate within-person and between-person effects
Raw panel regressions can mix two different questions: whether people with a higher typical predictor value have a higher outcome, and whether a person has a higher outcome than usual when their predictor is higher than usual.
wb <- fit_within_between(
srl,
y = "effort",
x = c("efficacy", "monitoring"),
id = "name",
time = "day",
scope = "pooled",
min_train = 30
)
contextual(wb)
#> variable within between contextual S.E. 95% CI p
#> --------------------------------------------------------------------------------
#> efficacy 0.3688 0.5862 0.2174 0.1015 [0.011, 0.423] 0.0392
#> monitoring 0.1745 0.0978 -0.0767 0.0988 [-0.277, 0.124] 0.4427
#>
#> scope = pooled, model = within_between, estimator = ols, subject = .all, subgroup = .allThe contextual table keeps these components explicit rather than silently assigning one interpretation to a raw-score coefficient.
Stabilise and explain differences between people
Individual coefficients vary because processes differ and because estimates are noisy. Pooling estimates the coefficient distribution; shrinkage produces stabilised person-specific coefficients.
pooled_coefs <- pool_coefs(fit)
shrunk_coefs <- shrink_coefs(fit)
pooled_coefs
#> POOLED PERSON EFFECTS
#> Method random effects (DerSimonian-Laird)
#> People 36
#> Terms 4
#>
#> term k pooled 95% CI sd_obs tau I2 Q p
#> ----------------------------------------------------------------------------------
#> (Intercept) 36 58.9356 [53.50, 64.38] 14.418 15.982 0.991 <1e-04
#> efficacy 36 0.2890 [0.20, 0.38] 0.269 0.251 0.910 <1e-04
#> monitoring 36 0.1956 [0.09, 0.30] 0.297 0.272 0.915 <1e-04
#> efficacy_lag1 36 0.0222 [-0.01, 0.05] 0.092 0.031 0.159 0.204
#>
#> sd_obs = spread you see; tau = spread that is REAL
#> I2 = share of the observed spread that is real
head(shrunk_coefs)
#> SHRUNKEN PERSON EFFECTS
#> People 6
#> Terms 1
#>
#> subject term raw S.E. weight shrunken
#> --------------------------------------------------------------
#> Aisha (Intercept) 77.3251 1.5811 0.990 77.1469
#> Alice (Intercept) 60.4228 1.5546 0.991 60.4088
#> Anika (Intercept) 47.0761 1.8153 0.987 47.2271
#> Astrid (Intercept) 68.5023 1.6127 0.990 68.4059
#> Bjorn (Intercept) 52.1594 1.7829 0.988 52.2427
#> Bob (Intercept) 73.1308 1.4604 0.992 73.0133
#>
#> weight = how much of the person's own estimate is keptSubgroup and treatment-effect workflows follow the same principle:
test what the data identify, retain person-level uncertainty and
failures, and use pooled quantities as comparisons rather than
replacements for individual processes. See
test_subgroups(), find_subgroups(),
fit_effects(), and fit_heterogeneity() for
those analyses.
Move to dynamic networks when the question is multivariate
When the target is a system of lagged and contemporaneous relations rather than one outcome, use the network estimators on the same panel:
net <- fit_mlvar(
srl,
vars = c("efficacy", "monitoring", "effort"),
id = "name",
beep = "day"
)
edges(net)
coefs(net)The regression and network layers deliberately share
coefs() and a common idiographic vocabulary while retaining
result structures appropriate to their different estimands.