【问题标题】:Selecting randomly from two arrays based upon condition in Python根据Python中的条件从两个数组中随机选择
【发布时间】:2019-02-13 18:34:50
【问题描述】:

假设我有两个长度相等的数组:

a = [0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,0,1]
b = [0,1,1,0,1,0,0,1,1,0,0,1,1,0,1,0,0]

现在我想从这两个数组中提取元素,按照给定的顺序,通过随机选择 a 和 b 之间的值,它们形成一个长度与 a 和 b 相同的新数组,比例为 a:b = 4.68 即对于从 a 中选取的每 1 个值,在结果数组中应该从 b 中选取 4.68 个值。

如此有效的结果数组可能是这样的:

res = [0,1,1,0,1, 1(from a) ,0(from a),1,1,0,0,1,1,0, 0(from a),0,0]

res 数组有:前 5 个值来自 b,第 6 和第 7 个来自 a,第 8-14 个来自 b,第 15 个来自 a,第 16-17 个来自 b

给定 res 数组示例中 a:b 值的总体比率为 a:b 4.67(a = 3,b = 14)

因此,在两个数组之间,必须随机选择值,但是需要保持顺序,即不能从一个数组中获取第 7 个值,而从另一个数组中获取第 3 个值。如果要填充到结果数组中的值是第 3 个,则选择是在两个输入数组的第三个元素之间随机选择。此外,还需要保持整体比率。

能否请您帮助我开发一种有效的 Pythonic 方式来实现此结果解决方案?解决方案不必与每次运行 w.r.t 值保持一致

【问题讨论】:

  • 你能用 numpy 吗?
  • 比率是否必须尽可能接近精确,还是只是概率?
  • 可以使用 numpy 。比率需要尽可能接近小数点后两位
  • @raul:所以要明确一点,选择不是独立的?如果偶然选择了来自a 的前三个值作为来自res 的前三个值,那么res 中的所有其他值必须来自b,对吗?
  • @ShadowRanger 没错

标签: python arrays python-2.7


【解决方案1】:

Barmar's answer 借用a_count 计算(因为它似乎有效,我懒得重新发明它),这个解决方案保留了从ab 中选择的值的顺序:

from future_builtins import zip  # Only on Python 2, to avoid temporary list of tuples
import random

# int() unnecessary on Python 3
a_count = int(round(1/(1 + 4.68) * len(a)))

# Use range on Python 3, xrange on Python 2, to avoid making actual list
a_indices = frozenset(random.sample(xrange(len(a)), a_count))

res = [aval if i in a_indices else bval for i, (aval, bval) in enumerate(zip(a, b))]

这里的基本思想是,您确定需要多少 a 值,获取该大小的可能索引的唯一样本,然后并行迭代 ab,保持 a 值用于选定的索引,b 用于所有其他索引。

如果您不喜欢 list 推导式的复杂性,您可以使用不同的方法,复制 b,然后一一填写 a 值:

res = b[:]  # Copy b in its entirety

# Replace selected indices with a values
# No need to convert to frozenset for efficiency here, and it's clean
# enough to just iterate the sample directly without storing it
for i in random.sample(xrange(len(a)), a_count):
    res[i] = a[i]

【讨论】:

  • 得到这个类型错误:不能将序列乘以非整数类型的'float'
  • @raul:是的,我忘了这是针对 Python 2 的。只需要 int 转换(已经编辑),因为 Python 2 上的 round 总是返回 float(在 Python 3 上,它仅在传递第二个参数时返回float,对于单个参数返回int)。旁注:Python 2 reaches end-of-life in less than a year。新代码应该真正针对 Python 3。
  • 你太棒了。感谢你和 Barmar。这是我正在开发的基于距离权重的集成模型,你们提供了一种计算它的绝妙方法
【解决方案2】:

我相信这应该可行。您指定要从 a 中获得多少(您可以简单地使用您的比率来计算该数字),您随机生成数字的“掩码”并从 a 中选择或基于截止值(请注意,您只排序以找出截止,但您稍后会使用未排序的掩码)

import numpy as np

a = [0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,0,1]
b = [0,1,1,0,1,0,0,1,1,0,0,1,1,0,1,0,0]

mask = np.random.random(len(a))
from_a = 3
cutoff = np.sort(mask)[from_a]

res = []
for i in range(len(a)):
    if (mask[i]>=cutoff):
        res.append(a[i])
    else:
        res.append(b[i])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-07
    相关资源
    最近更新 更多