cleverly.datasets.make_biased_sample#

cleverly.datasets.make_biased_sample(n_population: int = 4000, *, seed: int | Generator | None = None, heterogeneity: float = 1.2, backend: Literal['pandas', 'polars'] | str | None = None) → tuple[Any, dict[str, float]][source]#

A sample selected with known, unequal probabilities from a known population.

Draws n_population rows, keeps each with probability P(S = 1 | W1), and returns only the kept rows – so the frame is smaller than n_population, by design. It carries two extra columns: sampling_prob, the known selection probability, and sampling_weight, its reciprocal.

This is the survey/selection-bias case with everything known, which makes it the process that can actually test the claim in cleverly.data.weighting: because selection depends only on observed data and w = 1 / P(S = 1 | W1), the tilted law dP_w is the population law, so a weighted fit estimates the population ATE. An unweighted fit estimates the ATE among the selected, which is a different number here – reported as truth["ate_selected"] – and that gap is what a test asserts the weighting closes.

Parameters:
n_populationint

Size of the population the sample is drawn from, not of the sample.

seedint, Generator, or None

Seed or NumPy random generator.

heterogeneityfloat

Strength of the effect modification that makes the sampled population’s estimand differ from the population one.

backend{“pandas”, “polars”, “pyarrow”} or None, default=None

Dataframe backend. None uses pandas when installed, then the first available backend.

Returns:
dataframe

The selected sample, with the design weights that undo the selection.

truthdict of str to float

The population estimands, plus ate_selected (the estimand an unweighted analysis targets), n_population and n_selected.