+1 got this in a comment to a Python code snippet through the chat interface
frac = 0.25 # 25 % of each group
sampled = df.filter(
pl.int_range(pl.len()) # 0…n-1 per group
.shuffle() # random order :contentReference[oaicite:3]{index=3}
.over("group") # windowed by the grouping column(s) :contentReference[oaicite:4]{index=4}
< (pl.len().over("group") * frac).ceil()
)