在使用itertools.product时生成随机数

3

我正在使用生成器函数和itertools.product来创建有序数字列表,以便创建每个可能的数字配对:

def gen(lowerBound, upperBound, stepSize = 1):
    for steppedVal in np.arange(lowerBound, upperBound, stepSize):
        yield steppedVal

for vectors in it.product(gen(3,6), gen(10,30,5)):
    print(vectors)

结果如预期,生成了这样的数据集:

(3, 10)
(3, 15)
(3, 20)
(3, 25)
(4, 10)
(4, 15)
(4, 20)
(4, 25)
(5, 10)
(5, 15)
(5, 20)
(5, 25)

然而,我的问题在于接下来的步骤。我想在生成器函数中添加一个子句,用一个范围内的随机数替换步进值。当我尝试以下代码时:
def gen(useRandom, lowerBound, upperBound, stepSize = 1):
    if useRandom:
        randomVal = random.uniform(lowerBound, upperBound)
        yield randomVal
    else:
        for steppedVal in np.arange(lowerBound, upperBound, stepSize):
            yield steppedVal

for vectors in itertools.product(gen(True,3,6), gen(False,10,30,5)):
    print(vectors)

我明白您的意思,这并不是我想要的:

我得到了这个结果,但这并不是我想要的:

(4.4163620543645585, 10)
(4.4163620543645585, 15)
(4.4163620543645585, 20)
(4.4163620543645585, 25)

如何修改这段代码,以使数据集中的每个随机数都是唯一的,而不必在事后更改数据集,因为这会增加巨大的计算开销。 (实际数据集包含十几个变量,每个变量有10-20个步骤)。

编辑说明,以下是所需输出:

(4.1802347587349857, 10)
(3.7128578913746897, 15)
(5.8912734809721957, 20)
(4.4163620543645585, 25)

编辑2,为了更加明确,我不想使用zip函数,因为这也应该是可能的输出:

for vectors in itertools.product(gen(True,3,6), gen(False,10,30,5), gen(False,5,10):
    print(vectors)

(Some Random Number, 10, 5)
(Some Random Number, 10, 6)
(Some Random Number, 10, 7)
(Some Random Number, 10, 8)
(Some Random Number, 10, 9)
(Some Random Number, 15, 5)
(Some Random Number, 15, 6)
(Some Random Number, 15, 7)
(Some Random Number, 15, 8)
(Some Random Number, 15, 9)
(Some Random Number, 20, 5)
(Some Random Number, 20, 6)
(Some Random Number, 20, 7)
(Some Random Number, 20, 8)
(Some Random Number, 20, 9)
(Some Random Number, 25, 5)
(Some Random Number, 25, 6)
(Some Random Number, 25, 7)
(Some Random Number, 25, 8)
(Some Random Number, 25, 9)

第二个和第三个产生器的每一对仍然存在,这是关键部分。

1
我不明白你的问题?期望的输出是什么? - rafaelc
你想让那些 4.41... 的值变成 3 到 6 之间的随机数吗? - Patrick Haugh
完成了,感谢你的所有帮助! - Nathan
1
itertools.product(gen(False,3,6), gen(False,10,30,5), gen(False,5,10))将会有345=60个输出,但是看起来你想要的是product(gen(True), gen(False), gen(False)),它将会有4*5=20个输出。我不认为你只用product就能得到你想要的效果。你需要使用随机生成器和zip - mtrw
1
类似于 zip(random_gen, product(range1, range2)) 这样的代码应该可以得到你想要的结果。 - mtrw
显示剩余4条评论
1个回答

3
您的生成器只调用了 random.uniform 一次。我认为您想要这样:
def gen(useRandom, lowerBound, upperBound, stepSize = 1):
    for steppedVal in np.arange(lowerBound, upperBound, stepSize):
        if useRandom:
            randomVal = random.uniform(lowerBound, upperBound)
            yield randomVal
        else:
            yield steppedVal

现在,你的输出变成了:
(4.229914739995998, 10)
(4.229914739995998, 15)
(4.229914739995998, 20)
(4.229914739995998, 25)
(5.52362641577289, 10)
(5.52362641577289, 15)
(5.52362641577289, 20)
(5.52362641577289, 25)
(4.507985392309242, 10)
(4.507985392309242, 15)
(4.507985392309242, 20)
(4.507985392309242, 25)

这个代码片段展示了三个不同的随机值,分别对应了生成器第一次运行时产生的三个结果。

注意,你也可以尝试使用random.randrange,它会从指定的范围中返回一个随机整数,范围可以通过指定开始值、终止值和步长来确定。如果你将生成器函数中的random.uniform(lowerBound, upperBound)替换为random.randrange(lowerBound, upperBound, stepSize),则会得到如下输出:

(5, 10)
(5, 15)
(5, 20)
(5, 25)
(3, 10)
(3, 15)
(3, 20)
(3, 25)
(3, 10)
(3, 15)
(3, 20)
(3, 25)

这一次,在每个迭代中,生成器从集合[3、4、5]中随机选择一个数。请注意,这并不一定会在每个迭代中产生唯一的数字!如果您正在寻找这种结果,可以使用random.shuffle


我曾经有类似的东西,但是我希望每个随机值都是唯一的,我不想像你这里创建一个n个随机数的集合。 - Nathan
1
你能否更新你的问题,包括所需输出的示例?对我来说还不是很清楚。 - mtrw
1
@Nathan,听起来你想要的更像是 zip(generator_of_random_numbers, gen(lower, upper, step)) 而不是 product - Patrick Haugh
据我理解,zip 只进行直接配对。但是如果我有多个变量,我仍然希望得到每个可能的配对,唯一的限制是如果与一个随机数配对,那么该数字应该是随机的。 - Nathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接