def group_effect_draws_table(
fit: Any,
groups: Sequence[str] | str | None = None,
coefficients: Sequence[str] | str | None = None,
ndraws: int | None = None,
seed: int = 1,
max_rows: int = 1_000_000,
) -> pd.DataFrame:
arrays = _group_arrays(fit)
requested_groups = (
None if groups is None else ([groups] if isinstance(groups, str) else list(groups))
)
if requested_groups is not None:
missing = sorted(set(requested_groups) - set(arrays))
if missing:
raise GP3BayesError("Unknown grouping factors: " + ", ".join(missing) + ".")
requested_coef = (
None
if coefficients is None
else ([coefficients] if isinstance(coefficients, str) else list(coefficients))
)
max_rows = _integer(max_rows, "max_rows")
if ndraws is not None:
ndraws = _integer(ndraws, "ndraws")
if seed < 0:
raise GP3BayesError("`seed` must be one non-negative integer.")
rng = np.random.default_rng(seed)
pieces: list[pd.DataFrame] = []
total = 0
for group, (a4, levels, coefs) in arrays.items():
if requested_groups is not None and group not in requested_groups:
continue
flat = a4.reshape(-1, a4.shape[2], a4.shape[3])
ids = np.arange(flat.shape[0])
if ndraws is not None and len(ids) > ndraws:
ids = np.sort(rng.choice(ids, ndraws, replace=False))
keep = coefs if requested_coef is None else [c for c in coefs if c in requested_coef]
for coef in keep:
ci = coefs.index(coef)
total += len(ids) * len(levels)
if total > max_rows:
raise GP3BayesError(
"Requested draw table exceeds `max_rows`; reduce selectors/draws or increase `max_rows` explicitly."
)
values = flat[ids, :, ci]
pieces.append(
pd.DataFrame(
{
"group": group,
"level": np.repeat(levels, len(ids)),
"coefficient": coef,
"draw": np.tile(ids + 1, len(levels)),
"value": values.T.reshape(-1),
}
)
)
if not pieces:
raise GP3BayesError("No requested group-effect draws were available.")
return pd.concat(pieces, ignore_index=True)