【问题标题】:Python random sample selection based on multiple conditionsPython基于多个条件的随机样本选择
【发布时间】:2021-08-10 04:57:12
【问题描述】:

我想在 python 中从以下 df 中进行随机样本选择,这样至少 65% 的结果样本应该具有黄色并且所选数量的累积总和小于或等于 18。

原始数据集:

Date        Id      color       qty
02-03-2018  A       red         5
03-03-2018  B       blue        2
03-03-2018  C       green       3
04-03-2018  D       yellow      4
04-03-2018  E       yellow      7
04-03-2018  G       yellow      6
04-03-2018  H       orange      8
05-03-2018  I       yellow      1
06-03-2018  J       yellow      5

我有总数量。已覆盖选定条件,但仍停留在如何继续整合 % 条件:

df2 = df1.sample(n=df1.shape[0])

df3= df2[df2.qty.cumsum()

所需数据集:

Date        Id      color       qty
03-03-2018  B       blue        2
04-03-2018  D       yellow      4
04-03-2018  G       yellow      6
06-03-2018  J       yellow      5

或者是这样的:

Date        Id      color       qty
02-03-2018  A       red         5
04-03-2018  D       yellow      4
04-03-2018  E       yellow      7
05-03-2018  I       yellow      1

任何帮助将不胜感激!

提前致谢。

【问题讨论】:

  • 有办法回答你的问题,但我想提出一个框架挑战。我认为这个问题没有意义。假设我将您的问题扩展为“至少 65% 蓝眼睛且总年龄为 100 岁的人的随机样本”。在没有上下文的情况下,我们必须将“随机”解释为“从所有可能的选择中随机选择,使得所有选择都具有相同的可能性”。大约有 1B 蓝眼睛的人,“随机样本”的平均大小可能在 2B 左右(完全忽略您的年龄要求,这可能是有原因的)。你还有什么其他限制?

标签: python pandas


【解决方案1】:
  1. 使用'yellow' 过滤行并选择至少占总样本量 65% 的随机样本

    import random
    yellow_size = float(random.randint(65,100)) / 100
    df_yellow = df3[df3['color'] == 'yellow'].sample(yellow_size*sample_size)
    
  2. 用其他颜色过滤行并为剩余的样本量选择一个随机样本。

    others_size = 1 - yellow_size
    df_others = df3[df3['color'] != 'yellow].sample(others_size*sample_size)
    
  3. 将它们结合起来并随机排列。

    df_sample = pd.concat([df_yellow, df_others]).sample(frac=1)
    

更新:

如果您想同时检查这两个条件,这可能是一种方法:

import random

df_sample = df

while sum(df_sample['qty']) > 18:
    yellow_size = float(random.randint(65,100)) / 100
    df_yellow = df[df['color'] == 'yellow'].sample(yellow_size*sample_size)
    others_size = 1 - yellow_size
    df_others = df[df['color'] != 'yellow'].sample(others_size*sample_size)
    df_sample = pd.concat([df_yellow, df_others]).sample(frac=1)

【讨论】:

  • 太棒了,感谢@panktijk 的快速响应!唯一的问题是我们如何确保生成的数据集 (df_sample) 的数量之和也小于或等于 18。
  • 是的,但我们希望在样本选择时两个条件同时为真。这有意义吗?
  • 啊,好吧!我以为您想从已过滤的数据框中进行采样。我正在旅行。给我一些时间,我会研究如何将这两个条件结合在一起。
  • 所以另一种方法是继续生成样本,直到满足您的条件。我仍然建议您继续使用顺序方法,即首先计算 df3(就像您目前正在做的那样),然后从中采样行。
  • 这里唯一需要注意的是——我们最终可能会选择随机样本,其中累积和条件为真,但我们可能无法获得足够的颜色条件,在选择样本时应进行检查。跨度>
【解决方案2】:

我会使用这个包将你的黄色过度采样成一个具有你想要的平衡的新样本:

https://imbalanced-learn.readthedocs.io/en/stable/over_sampling.html

从那里随机选择项目并检查总和,直到你得到你想要的集合。

时间复杂度较低的方法是对数据框长度范围内的二进制搜索,并使用二进制搜索项作为样本大小,直到获得所需的 cumsum。假设特征是对称分布的。

【讨论】:

    【解决方案3】:

    我认为这个例子对你有帮助。我添加列 df2['yellow_rate'] 并计算速率。您只检查 df2.iloc[df2.shape[0] - 1]['yellow_rate'] 值。

    df1=pd.DataFrame({'id':['A','B','C','D','E','G','H','I','J'],'color':['red','bule','green','yellow','yellow','yellow','orange','yellow','yellow'], 'qty':[5,2, 3, 4, 7, 6, 8, 1, 5]})
    df2 = df1.sample(n=df1.shape[0])
    df2['yellow_rate'] =  df2[df2.qty.cumsum() <= 18]['color'].apply( lambda x : 1 if x =='yellow' else 0)
    df2 = df2.dropna().append(df2.sum(numeric_only=True)/ df2.count(numeric_only=True), ignore_index=True)
    

    【讨论】:

    • 嗨@mtgarden,谢谢。看起来代码只是确保cumsum of qty&lt;=18,但不能确保 65% 的结果数据帧包含“黄色”。我们将要求两个条件同时为真。还有什么我们可以尝试的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 2015-11-27
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多