-
Notifications
You must be signed in to change notification settings - Fork 1k
[Repo Assist] fix: support multiple treatments in PlaceboTreatmentRefuter (closes #251) #1467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -83,6 +83,60 @@ def refute_estimate(self, show_progress_bar=False): | |||||||||||||||||||||||||||||
| return refute | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def _get_placebo_names(treatment_names: List[str]) -> List[str]: | ||||||||||||||||||||||||||||||
| """Return placebo column name(s) for the given treatment name(s). | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Single-treatment case uses ``"placebo"`` for backward compatibility; | ||||||||||||||||||||||||||||||
| multi-treatment case prefixes each name with ``"placebo_"``. | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
| if len(treatment_names) == 1: | ||||||||||||||||||||||||||||||
| return ["placebo"] | ||||||||||||||||||||||||||||||
| return ["placebo_" + t for t in treatment_names] | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def _generate_random_placebo(data: pd.DataFrame, treatment_name: str, type_dict: Dict) -> pd.Series: | ||||||||||||||||||||||||||||||
| """Generate a single random placebo column matching the dtype of *treatment_name*.""" | ||||||||||||||||||||||||||||||
| dtype_name = type_dict[treatment_name].name | ||||||||||||||||||||||||||||||
| n = data.shape[0] | ||||||||||||||||||||||||||||||
| if "float" in dtype_name: | ||||||||||||||||||||||||||||||
| logger.info( | ||||||||||||||||||||||||||||||
| "Using a Normal Distribution with Mean:{} and Variance:{}".format( | ||||||||||||||||||||||||||||||
| DEFAULT_MEAN_OF_NORMAL, | ||||||||||||||||||||||||||||||
| DEFAULT_STD_DEV_OF_NORMAL, | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| return pd.Series( | ||||||||||||||||||||||||||||||
| np.random.randn(n) * DEFAULT_STD_DEV_OF_NORMAL + DEFAULT_MEAN_OF_NORMAL, | ||||||||||||||||||||||||||||||
| index=data.index, | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| elif "bool" in dtype_name: | ||||||||||||||||||||||||||||||
| logger.info( | ||||||||||||||||||||||||||||||
| "Using a Binomial Distribution with {} trials and {} probability of success".format( | ||||||||||||||||||||||||||||||
| DEFAULT_NUMBER_OF_TRIALS, | ||||||||||||||||||||||||||||||
| DEFAULT_PROBABILITY_OF_BINOMIAL, | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| return pd.Series( | ||||||||||||||||||||||||||||||
| np.random.binomial(DEFAULT_NUMBER_OF_TRIALS, DEFAULT_PROBABILITY_OF_BINOMIAL, n).astype(bool), | ||||||||||||||||||||||||||||||
| index=data.index, | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| elif "int" in dtype_name: | ||||||||||||||||||||||||||||||
| logger.info( | ||||||||||||||||||||||||||||||
| "Using a Discrete Uniform Distribution lying between {} and {}".format( | ||||||||||||||||||||||||||||||
| data[treatment_name].min(), data[treatment_name].max() | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| return pd.Series( | ||||||||||||||||||||||||||||||
| np.random.randint(low=data[treatment_name].min(), high=data[treatment_name].max() + 1, size=n), | ||||||||||||||||||||||||||||||
| index=data.index, | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| elif "category" in dtype_name: | ||||||||||||||||||||||||||||||
| categories = data[treatment_name].unique() | ||||||||||||||||||||||||||||||
| logger.info("Using a Discrete Uniform Distribution with the following categories:{}".format(categories)) | ||||||||||||||||||||||||||||||
| return pd.Series(np.random.choice(categories, size=n), index=data.index).astype("category") | ||||||||||||||||||||||||||||||
|
Comment on lines
+134
to
+136
|
||||||||||||||||||||||||||||||
| categories = data[treatment_name].unique() | |
| logger.info("Using a Discrete Uniform Distribution with the following categories:{}".format(categories)) | |
| return pd.Series(np.random.choice(categories, size=n), index=data.index).astype("category") | |
| treatment = data[treatment_name] | |
| categories = treatment.cat.categories | |
| logger.info("Using a Discrete Uniform Distribution with the following categories:{}".format(categories)) | |
| return pd.Series( | |
| pd.Categorical( | |
| np.random.choice(categories, size=n), | |
| categories=categories, | |
| ordered=treatment.cat.ordered, | |
| ), | |
| index=data.index, | |
| ) |
Copilot
AI
Apr 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the PERMUTE path, data[treatment_names].iloc[permuted_idx].values converts the permuted columns to a NumPy array, which can silently coerce dtypes (e.g., categorical -> object, mixed dtypes -> object). That can change estimator behavior compared to the original treatment columns. Consider permuting each treatment column as a pandas Series (preserving dtype) and then resetting its index to data.index before assignment so the permutation applies by position without index alignment undoing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_generate_random_placeboinfers dtype via substring checks ontype_dict[treatment_name].name(e.g.,"int" in dtype_name). This is brittle for pandas extension dtypes likeInt64/Float64(case mismatch) and can lead to the new ValueError even when the column is a valid numeric type. Prefer usingpandas.api.typeshelpers (is_float_dtype/is_integer_dtype/is_bool_dtype/is_categorical_dtype) on the actual dtype/Series for a robust check.