通过基于随机值的过滤使用列表理解来产生10(或更少)均匀分布的随机浮点数

Rod*_*ogo 1 python

出于一些奇怪的原因,让我们说我想使用List Comprehensions - 而仅使用List Comprehensions - 来生成10个大于0.5的随机数.对于问题的"10个随机数"部分,我们将使用:

samples = [ random.random() for x in range(10) ]
Run Code Online (Sandbox Code Playgroud)

现在,对于"大于0.5",如何使用LC实现?

samples = [ random.random() for x in range(10) if ??? ]
Run Code Online (Sandbox Code Playgroud)

nin*_*cko 6

你在描述什么称为拒绝抽样,这是一个坏主意.例如,如果您只想要数字>0.999,则生成它们需要花费1000倍的时间.


最好的办法

正确的方法是使用另一种采样技术,例如使用CDF的反转(累积密度函数),然后执行[inverseCDF(random()) for _ in range(10)].在你的情况下,就像GaretJax建议的那样,[0.5+random()/2 for _ in range(10)]


意图

我认为你的意图是能够根据列表理解的整个表达式进一步过滤.在这种情况下,你会把你的可迭代(在这里用括号而不是[...]用于懒惰,虽然没关系)在另一个理解中:

[r for r in (random.random() for x in range(10)) if r>0.5]
Run Code Online (Sandbox Code Playgroud)

有关可以处理拒绝的这些行的更好解决方案,请参阅"仅限列表推导的解决方案"部分或eryksun的答案.


发电机解决方案

(请参阅下面的列表理解解决方案)

您可以对任何线性范围执行此操作.但是,如果拒绝功能是任意复杂的,那么进行拒绝采样的一般方法如下.(同样,一个非常糟糕的想法,除非你知道你在做什么,效率无关紧要.)

from random import random
from itertools import *

def randoms():
    while True:
        yield random()

def rejectionSample(pred, n):
    return islice(filter(pred, randoms()), n)
Run Code Online (Sandbox Code Playgroud)

例:

>>> print( list(rejectionSample(lambda x:x>0.5)) )
[0.6656564857979361, 0.9850389778418555, 0.9607471536139308, 0.9191328900300356, 0.810783093197139]
Run Code Online (Sandbox Code Playgroud)

你也可以这样做:

def rejectionSample(pred, n):
    count = 0
    while count<n:
        r = random()
        if pred(r):
            yield r
            count += 1 
Run Code Online (Sandbox Code Playgroud)

仅限列表推导的解决方案

然而,由于要使用列表理解,这意味着你的理解的表达部分不能失败,所以你必须以某种方式嵌入在修真while循环.单独使用单个lambda函数是不可能的,但只要我们有一些递归/循环原语,我们就可以将它拉下来,例如......

[next(filter(pred,randoms())) for _ in range(10)]
Run Code Online (Sandbox Code Playgroud)

(如果你真的想要一个单行列表理解,randoms()可以重写为(random() for _ in count()).)同样,如果你很容易找到你的特定发行版的分析逆累积分布函数,这是不必要的.


编辑:我把它拿回来......它可能 ......只有lambdas ......

亲爱的上帝,我在世界NOOOOOO上发生了什么样的恐惧?

[
 (lambda f:f(f,random()))(lambda self,r:r if r>0.5 else self(self,random()))
 for _ in range(10)
]
Run Code Online (Sandbox Code Playgroud)