如何 sample/group 行数据框来修复组内的特定分布?

how to sample/group rows of dataframe to fix specific distributions within a group?

我有一个包含列 a 的 DataFrame c

import numpy as np
a = np.random.randint(0,10, size=(100))
c = pd.DataFrame(a, columns=['a'])

我想对 c 的行进行 运行dom 分组,这样每组中有 5 行,并且每组中有 1 行 a < 3

例如:

[1,2,3,2,10]  <-- good group 
[1,1,3,4,6]  <-- good group
[2,4,7,3,7] <-- bad group

并且如果我 运行 行满足此条件(例如我 运行 行 a < 1)然后忽略数据框的其余部分

目前我通过创建一个新列 group_id 并按条件分隔 c 然后从它们中迭代抽样直到我 运行 候选人:

c['group_id'] = None
c_w_small_a = c[c.a < 3].copy()
c_w_large_a = c[c.a >= 3].copy()
group_id = 0
while len(c_w_small_a) >= 1 and len(c_w_large_a) >= 4:
   c.loc[c_w_small_a.sample(1, replace=False).index, 'group_id'] = group_id
   c.loc[c_w_large_a.sample(4, replace=False).index, 'group_id'] = group_id
   group_id += 1

c = c[c.group_id.apply(lambda x,x is not None)] # filter rows without id
c_groups = c.groupby('group_id')

这种方法的问题是我无法将这种方法推广到子集相互重叠的更复杂的条件下。比如

at most 2 rows with a > 2 and at least 1 rows with 'a == 3'.

我不知道如何以这种方式对其进行编码以最大化我可以通过该分组获得的组数。例如,如果 a ==3 非常有限,那么我不希望 a> 2 选择 3,即使它满足它的条件。

我不确定,但我认为您描述的问题是 NP 完全问题,为此我建议您考虑启发式方法以找到令人满意的解决方案。为此,您可以编写如下所示的贪婪启发式算法:

def is_satisfying(group):
...     if (np.sum(group > 2) > 2) or (np.sum(group == 3) < 1): 
...             return False
...     else:
...             return True

然后构建一个组,你可以这样写:

group = []
while len(group) != 4 : 
...     np.append(group, df['a'].sample(n=1))
...     if not is_satisfying(group):
...             group = group[:-1]

并且为了标记已经添加到组中的元素,您使用了一些数据结构,使您能够在采样之前过滤数据帧