算法这个词可能太强了,因为对我来说这意味着形式主义和出版,但是有一种方法可以选择具有精确比例的子集(假设你的百分比从样本宇宙中产生整数),而且它比其他简单得多提出的解决方案。我已经构建了一个并对其进行了测试。
顺便说一句,我很抱歉在这里反应迟钝,但是这些天我的时间有限。我相当快地编写了一个硬编码的解决方案,从那以后我一直在将它重构为一个体面的通用实现。因为一直很忙,所以还没说完,但我不想再耽误回答了。
方法:
基本上,您将分别考虑每一行,并根据您的标准是否为您提供选择每个列值的空间来决定它是否可选。
为此,您需要将每个列规则(例如,40% 的男性、60% 的女性)视为一个单独的目标(例如,给定所需的 100 子集大小,您正在寻找 40 个男性、60 个女性)。为每个人做一个计数器。
然后循环,直到您创建了子集,或者您检查了示例 Universe 中的所有行但没有找到匹配项(请参阅下面的内容)。这是伪代码中的循环:
- Randomly select a row.
- Mark the row examined.
- For each column constraint:
* Get the value for the relevant column from the row
* Test for selectability:
If there's a value target for the value,
and if we haven't already selected our target number of incidences of this value,
then the row is selectable with respect to this column
* Else: the row fails.
- If the row didn't fail, select it: add it to the subset
这就是它的核心。它将提供一个与您的规则匹配的子集,否则它将无法这样做......这让我想到了当我们找不到匹配项时会发生什么。
不满意:
正如其他人所指出的,对于任意样本宇宙,并不总是能够满足任意一组规则。即使假设规则是有效的(每个值的百分比总和为 100),子集大小小于宇宙大小,并且宇宙确实包含足够的具有每个选定值的个体来达到目标,如果值实际上并不是独立分布的。
考虑样本宇宙中所有男性都是澳大利亚人的情况:在这种情况下,您只能选择尽可能多的男性,您可以选择澳大利亚人,反之亦然。因此,即使我们选择的所有澳大利亚人都是男性,也无法从这样的宇宙中满足一组约束(子集大小:100;男性:40%;澳大利亚人 10%)。
如果我们改变约束条件(子集大小:100;男性:40%;澳大利亚人 40%),现在我们可以创建一个匹配的子集,但是我们选择的所有澳大利亚人都必须是男性。如果我们再次更改约束条件(子集大小:100;男性:20%;澳大利亚人 40%),现在我们可以制作一个匹配的子集,但前提是我们不选择太多澳大利亚女性(不超过一半这个案例)。
在后一种情况下,选择顺序很重要。根据我们的随机种子,有时我们可能会成功,有时我们可能会失败。
出于这个原因,算法必须(我的实现确实)准备好重试。我认为这是一个耐心测试:问题是在我们决定约束与样本总体不兼容之前,我们愿意让它失败多少次。
适应性
该方法非常适合描述的 OP 任务:选择与给定标准匹配的随机子集。不适合回答一个稍微不同的问题:“是否有可能形成具有给定标准的子集”。
我对此的推理很简单:算法无法找到子集的情况是数据包含未知链接,或者标准允许样本宇宙中的子集数量非常有限。在这些情况下,任何子集的使用对于统计分析都是有问题的,至少在没有进一步考虑的情况下是这样。
但是为了回答是否可以形成子集的问题,这种方法是不确定的和低效的。最好使用其他人提出的更复杂的随机排序算法之一。
预验证:
发现并非所有子集都可以满足的直接想法是执行一些初始验证,并且可能分析数据以查看它是可回答的还是只能有条件回答的。
我的立场是,除了最初验证每个列规则是有效的(即列百分比总和为 100,或足够接近)并且子集大小小于全域大小之外,没有其他值得事先验证正在做。可以提出一个论点,即您可能想要检查宇宙中每个选定值是否包含足够多的个体(例如,宇宙中实际上有 40 名男性和 60 名女性),但我没有实现。
除此之外,任何识别群体中联系的分析本身都是耗时的,如果通过更多的重试来运行这个东西,你可能会得到更好的服务。也许这只是我缺乏统计背景的说法。
不完全是子集和问题
有人建议这个问题就像子集和问题。我认为这是微妙而显着的不同。我的推理如下:对于子集和问题,您必须形成并测试一个子集才能回答它是否符合规则的问题:在添加之前不可能(除非在某些边缘条件下)测试单个元素它到子集。
但是,对于OP的问题,这是可能的。正如我将解释的,我们可以随机选择行并单独测试它们,因为每行的权重为 1。