【问题标题】:Generate a list of 100 elements, with each element having a 50% chance of being 0, and a 50% chance of being a random number between 0 and 1生成一个包含 100 个元素的列表,每个元素有 50% 的可能性为 0,有 50% 的可能性为 0 到 1 之间的随机数
【发布时间】:2021-02-23 09:52:04
【问题描述】:

我对此很陌生,我正在努力自学。正如我在标题中所说,我正在尝试创建一个包含 100 个数字的列表,这些数字的元素有 50% 的可能性是 0,或者有 50% 的变化是 0 到 1 之间的数字。我把它做成了下面的那个。它可以工作,但它是一个非常乏味且编码不好的程序。任何提示如何使它变得更好?

import random
import numpy as np

#define a list of 100 random numbers between 0 and 1
randomlist = []
for i in range(0,100):
    n = random.uniform(0,1)
    randomlist.append(n)
print(randomlist)


#create a list of 100 numbers of 0's and 1's
def random_binary_string(length):
    
    sample_values = '01' # pool of strings
    result_str = ''.join((random.choice(sample_values) for i in range(length)))
    return (result_str)

l=100
x=random_binary_string(l)
x1=np.array(list(map(int, x)))
print(x1)


#combine both lists. Keep value if of the binary list if it is equal to zero. Else, substitute it by the value of randomlist
#corresponding to the index position
finalist=[]
for i in range(len(x1)):
    if x1[i]==0:
        finalist.append(x1[i])
    else:
        finalist.append(randomlist[i])
        
print(finalist)    

非常感谢!

【问题讨论】:

标签: python list random generate


【解决方案1】:

您可以通过嵌套这两个条件来简化代码。这避免了在内存中保留两个单独的列表然后在最后合并它们的需要。

randomlist = []
for i in range(0,100):
    if random.choice((0, 1)) == 1:
        randomlist.append(random.uniform(0,1))
    else:
        randomlist.append(0)

这非常简单明了,您可以将其重构为单个列表推导式。这更紧凑,但不太易读。

randomlist = [random.uniform(0,1) if random.choice((0, 1)) else 0 for i in range(0,100)]

在这里,我们还利用Python中0是falsey而1是truthy的事实稍微缩短了代码;即它们在布尔上下文中分别评估为FalseTrue。所以if random.choice((0, 1)) == 1可以简写为if random.choice((0, 1))

有点晦涩,您可以通过观察表达式B if not A else A 可以短路到表达式A and B 来进一步简化这一点(从某种意义上说,使用更少的代码)。如果您对布尔逻辑不是很熟悉,这不是很明显,但我认为您可以在纸上解决。

randomlist = [random.choice((0, 1)) and random.uniform(0,1) for i in range(0,100)]

演示:https://ideone.com/uGHS2Y

【讨论】:

  • [random.getrandbits(1) and random.uniform(0, 1) for i in range(100)] 应该明显更快。
  • 谢谢。我想这对于 100 个数字来说并不重要,但如果你需要几千个,这肯定是一个有用的优化。
【解决方案2】:

你可以尝试做这样的事情:

import random


def create_random_list():
    random_list = list()

    for _ in range(100):
        if random.choice((True, False)):
            random_list.append(0)
        else:
            random_list.append(random.uniform(0, 1))

    return random_list


randomly_generated_list = create_random_list()
print(len(randomly_generated_list), randomly_generated_list)
# 100 [x_0,...,x_99]

【讨论】:

    【解决方案3】:

    我提出这个方法:

    • 首先使用 random.choice 生成一个随机列表“A”和“B”。 50%“A”和 50%“B”
    • 然后用 0 到 1 之间的随机数替换“A”
    • 并将“B”替换为 0

    代码在这里:

    import random
    
    ll = [ random.choice(['A', 'B'])  for x in range(200)]
    print(ll, len(ll))
    
    for i in range(len(ll)):
        if ll[i] == 'A':
            ll[i]=random.random()
        else:
            ll[i]=0
    
    print(ll, len(ll))
    

    这里的代码更短:

    import random
    ll = [ random.choice([0, random.random()])  for x in range(200)]
    print(ll, len(ll), ll.count(0))
    

    【讨论】:

      【解决方案4】:

      由于您使用的是 Numpy,我可能会执行以下操作:

      1. 使用random.uniform 创建num_el 元素数组
        • 考虑排除上限的问题:[low, high)
      2. 创建一个布尔矩阵,其概率p=0.5 在真假之间:random.choice
      3. 使用矩阵将数组的一些元素设置为零,通过

      代码如下:

      num_el = 10
      p = 0.5
      
      res = np.random.uniform(0., 1., size=(1, num_el))
      bool_mat = np.random.choice(a=[False, True], size=(1, num_el), p=[p, 1-p])
      res[bool_mat] = 0.
      
      res  
      # array([[0.        , 0.51213168, 0.        , 0.68230528, 0.5287728 ,
      #         0.9072587 , 0.        , 0.43078057, 0.89735872, 0.        ]])
      

      【讨论】:

        【解决方案5】:

        使用的方法取决于您的目标是恰好一半的结果为零,还是让预期的零数为总数的一半。从您的问题中并不清楚您以哪种方式看待问题,因此我将这两种方法都实现为函数。

        如果您想要一个确定性的固定比例的零/非零,下面代码中的第一个函数可以解决问题。它创建一个具有所需数量的零和非零的列表,然后使用改组(我计时比采样更快)。如果你想要一半,那么显然n 的参数必须是偶数。

        如果您的目标是概率 50% 零,请使用第二个函数。

        import random
        
        # Exactly floor(n / 2) outcomes are zeros, i.e., exactly half when n is even.
        # This version is trivial to modify to give any desired proportion of zeros.
        def make_rand_list_v1(n = 100):
            m = n // 2
            n -= m
            ary = [random.random() for _ in range(n)] + [0] * m
            random.shuffle(ary)
            return ary
        
        # Each outcome has probability 0.5 of being zero
        def make_rand_list_v2(n = 100):
            return [random.getrandbits(1) and random.uniform(0, 1) for _ in range(n)]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-28
          • 2018-11-11
          • 2018-10-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多