【问题标题】:How to use numpy.random.choice in a list of tuples?如何在元组列表中使用 numpy.random.choice?
【发布时间】:2015-08-29 12:37:50
【问题描述】:

我需要以给定的概率进行随机选择,以便从列表中选择一个元组。

编辑: 每个元组的概率在概率列表中 不知道忘记参数替换,默认是none 使用数组而不是列表的同样问题

下一个示例代码给我一个错误:

import numpy as np

probabilit = [0.333, 0.333, 0.333]
lista_elegir = [(3, 3), (3, 4), (3, 5)]

np.random.choice(lista_elegir, 1, probabilit)

错误是:

ValueError: a must be 1-dimensional

我该如何解决?

【问题讨论】:

  • 如果只想绘制等概率的元素,可以使用标准库中的random.choice
  • 我有错误的 numpy 版本,所以我无法测试,但根据 the documentation,您是否尝试过将列表设为 numpy array?另外,您似乎缺少第三个参数replace

标签: python numpy random


【解决方案1】:

根据函数的文档,

a : 1-D array-like or int
    If an ndarray, a random sample is generated from its elements.
    If an int, the random sample is generated as if a was np.arange(n)

那么就这样

lista_elegir[np.random.choice(len(lista_elegir),1,p=probabilit)]

应该做你想做的。 (p= 根据评论添加;如果值一致则可以省略)。

它从 [0,1,2] 中选择一个数字,然后从您的列表中选择该元素。

【讨论】:

  • 在 Python 3.6 中,在对多个项目进行采样时,上述内容给了我一个错误:only integer scaler arrays can be converted to a scaler index。这不能通过转换为int 或使用range(len(x)) 而不是len(x) 来解决。一种解决方案是使用内联 for 循环:[x[i] for i in np.choice(len(x), n)] 工作正常
  • @Scipio 这是因为lista_elegir 是一个列表。使用np.asarray(lista_elegir)按索引访问。
【解决方案2】:

问题在于元组列表被解释为二维数组,而choice 仅适用于一维数组或整数(解释为“从范围中选择”)。见the documentation

因此解决此问题的一种方法是传递元组列表的len,然后选择具有相应索引(或索引)的元素,如other answer 中所述。如果您首先将lista_elegir 转换为np.array,这也适用于多个索引。但是,还有两个问题:

首先,你调用函数的方式,probabilit会被解释为第三个​​参数,replace是概率,即列表被解释为布尔值,这意味着您选择替换,但实际概率被忽略。您可以通过将第三个参数传递为[1, 0, 0] 来轻松检查这一点。请改用p=probabilit。其次,概率总和必须为 1,正好。你的只有0.999。看来您将不得不稍微倾斜概率,或者如果它们都相同(因此假设均匀分布),则将该参数保留为 None

>>> probabilit = [0.333, 0.333, 0.333]
>>> lista_elegir = np.array([(3, 3), (3, 4), (3, 5)]) # for multiple indices
>>> indices = np.random.choice(len(lista_elegir), 2, p=probabilit if len(set(probabilit)) > 1 else None)
>>> lista_elegir[indices]
array([[3, 4],
       [3, 5]])

【讨论】:

    【解决方案3】:

    我知道这篇文章很老了,但把它留在这里以防其他人在这里结束。

    对我有用的是将列表转换为 nparray。您可以随时将其转换回列表。

    import numpy as np
    
    numSamples = 2    
    probabilit = [0.333, 0.333, 0.333] 
    lista_elegir = [(3, 3), (3, 4), (3, 5)]
    
    lista_elegir_arr = np.array(lista_elegir)
    
    #make sure probabilities sum to 1, and if they are all the same they are not needed
    np.random.choice(lista_elegir_arr, numSamples, p = None)
    

    【讨论】:

    • 请注意,当您转换回来时,它将是列表列表,而不是元组列表。您还必须执行转换的第二步
    • 我运行了 sn-p,它给出了同样的错误:“ValueError: a must be 1-dimensional”
    • 还得到了 np.__version__ = 1.19.2 的 ValueError
    【解决方案4】:

    只使用随机数

    import random
    import numpy as np
    
    DIRECTIONS = [np.array([-1, 0]),
              np.array([0, 1]),
              np.array([1, 0]),
              np.array([0, -1])]
    
    random.choice(DIRECTIONS)
    

    结果得到了其中一个元组

    【讨论】:

      【解决方案5】:

      简单的英语解决方案

      numpy 1.19.2 版

      import numpy as np
      
      probs = [.1, .2, .7]
      vals = [(3, 0), (3, 1), (3, 2)]
      n_samples = 5  # choose so may elements from vals
      
      np.random.seed(1)  # fix random seed for reproducibility
      inds = np.random.choice(len(vals), n_samples, p=probs)
      rand_vals = [vals[ind] for ind in inds]
      print(rand_vals)
      

      输出

      [(3, 2), (3, 2), (3, 0), (3, 2), (3, 1)]
      

      【讨论】:

      • 遇到了同样的问题。我认为 o.p. 中的代码。应该管用。公平地说,Numpy 实现不是通用的(pythonic??),因为列表是列表(1D),即使其中的元素不是标量。 o.p. 中的代码如果列表元素是标量,它会工作得很好。为什么 Numpy 实现不允许这样做?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-04
      • 2021-06-05
      • 2018-07-15
      • 2013-03-11
      • 1970-01-01
      • 2017-08-19
      • 2013-09-30
      相关资源
      最近更新 更多