Following @orlp's approach, I would pivot as suggested, create a full combination, and then use the .select() method to filter the columns.
import polars as pl
import itertools
df = pl.DataFrame({
"id": [1, 2, 3, 1, 2, 3, 1, 2, 3],
"variable": ["x1", "x1", "x1", "x2", "x2", "x2", "x3", "x3", "x3"],
"favorite": ["APP", "APP", "WEB", "APP", "WEB", "APP", "APP", "APP", "WEB"]
})
action_through_app = (
df
.with_columns(pl.col.favorite == "APP")
.pivot(index="id", on="variable", values="favorite")
)
all_combinations = []
states = df["variable"].unique().to_list()
for r in range(1,len(states)+1):
all_combinations.extend(itertools.combinations(states, r))
def test_f(df):
return(
df.with_columns((pl.sum_horizontal(pl.all()) >= 0.6*pl.sum_horizontal(pl.all().is_not_null())).alias("target"))
)
new_rows = []
for i in range(len(all_combinations)):
df_filtered = action_through_app.select(all_combinations[i])
df_test = test_f(df_filtered).select(pl.col("target").sum()).to_series().to_list()
x = df_test[0]
new_rows.append({"loop_index": i, "size": x})
df_final = pl.DataFrame(new_rows)
This way i have this output:
shape: (7, 2)
┌────────────┬──────┐
│ loop_index ┆ size │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞════════════╪══════╡
│ 0 ┆ 2 │
│ 1 ┆ 2 │
│ 2 ┆ 2 │
│ 3 ┆ 1 │
│ 4 ┆ 2 │
│ 5 ┆ 1 │
│ 6 ┆ 2 │
└────────────┴──────┘