【问题标题】:how to get the index of numpy.random.choice? - python如何获取 numpy.random.choice 的索引? - Python
【发布时间】:2013-09-18 14:49:57
【问题描述】:

是否可以修改 numpy.random.choice 函数以使其返回所选元素的索引? 基本上,我想创建一个列表并随机选择元素而不替换

import numpy as np
>>> a = [1,4,1,3,3,2,1,4]
>>> np.random.choice(a)
>>> 4
>>> a
>>> [1,4,1,3,3,2,1,4]

a.remove(np.random.choice(a)) 将删除列表中具有它遇到的值的第一个元素(上例中的a[1]),它可能不是所选元素(例如,a[7])。

【问题讨论】:

  • 它可能不是选择的元素,但似乎两种情况无法区分。
  • enumerate 可能会工作
  • @Rob:不是真的。创建列表后,无论我删除哪个元素,它都保持相同的顺序很重要。
  • ...应该有一个函数np.random.argchoice(...)

标签: python random numpy


【解决方案1】:

也许晚了,但值得一提的是这个解决方案,因为我认为最简单的方法是:

a = [1, 4, 1, 3, 3, 2, 1, 4]
n = len(a)
idx = np.random.choice(list(range(n)), p=np.ones(n)/n)

这意味着您从索引中选择是一致的。在更一般的情况下,您可以通过以下方式进行加权采样(并返回索引):

probs = [.3, .4, .2, 0, .1]
n = len(a)
idx = np.random.choice(list(range(n)), p=probs)

如果您尝试多次这样做(例如 1e5),则所选索引的直方图将类似于 [0.30126 0.39817 0.19986 0. 0.10071] 在这种情况下是正确的。

无论如何,您应该从索引中选择并使用值(如果需要)作为它们的概率。

【讨论】:

    【解决方案2】:
    numpy.random.choice(a, size=however_many, replace=False)
    

    如果您想要一个无需替换的示例,请让 numpy 为您制作一个。不要重复循环和绘制项目。这会产生臃肿的代码和糟糕的性能。

    例子:

    >>> a = numpy.arange(10)
    >>> a
    array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    >>> numpy.random.choice(a, size=5, replace=False)
    array([7, 5, 8, 6, 2])
    

    在足够新的 NumPy(至少 1.17)上,您应该使用新的随机性 API,它解决了长期存在的性能问题,即旧 API 的 replace=False 代码路径不必要地在后台生成了输入的完整排列:

    rng = numpy.random.default_rng()
    result = rng.choice(a, size=however_many, replace=False)
    

    【讨论】:

    • 我不明白这是如何工作的。在这种情况下,“a”是什么?可以举个例子吗?
    • @HappyPy: a 与您的代码中的内容完全相同;它是我们想要从中获取样本的类数组对象。 size 是我们想要的样本中元素的数量,replace=False 要求提供没有替换的样本。结果将是一个形状为(however_many,) 的一维数组,其中包含您想要的样本。
    • 样本已经是“a”。我想直接使用“a”,这样我就可以控制还剩下多少元素并使用“a”执行其他操作。
    • @HappyPy:听起来你使用 numpy 都错了。如果a 已经是一个随机样本,但是您想从a 中提取元素而不进行替换,那么您实际上是在从a 中提取另一个随机样本。如果你真的,真的想连续从a 中删除元素,numpy 不太可能帮到你。
    【解决方案3】:

    这是一个简单的解决方案,只需从范围函数中选择即可。

    import numpy as np
    a = [100,400,100,300,300,200,100,400]
    I=np.random.choice(np.arange(len(a)))
    print('index is '+str(I)+' number is '+str(a[I]))
    

    【讨论】:

      【解决方案4】:

      除了使用choice,您还可以简单地random.shuffle您的数组,即

      random.shuffle(a)  # will shuffle a in-place
      

      【讨论】:

        【解决方案5】:

        与其他答案相比,这有点偏左,但我认为它可能有助于你在更大意义上尝试做的事情。您可以通过改组源数组中元素的索引来生成随机样本而无需替换:

        source = np.random.randint(0, 100, size=100) # generate a set to sample from
        idx = np.arange(len(source))
        np.random.shuffle(idx)
        subsample = source[idx[:10]]
        

        这将通过从源集(这里,大小为 100)中提取元素而不进行替换来创建一个样本(这里,大小为 10)。

        您可以使用剩余的索引值与未选择的元素进行交互,即:

        notsampled = source[idx[10:]]
        

        【讨论】:

          【解决方案6】:

          关于你的第一个问题,你可以反过来,从数组a的索引中随机选择,然后取值。

          >>> a = [1,4,1,3,3,2,1,4]
          >>> a = np.array(a)
          >>> random.choice(arange(a.size))
          6
          >>> a[6]
          

          但是如果您只需要随机样本而不需要替换,replace=False 就可以了。不记得什么时候第一次添加到random.choice,可能是1.7.0。因此,如果您运行的是非常旧的numpy,它可能无法正常工作。请记住,默认值为replace=True

          【讨论】:

          • 在这种情况下不需要列出并从中选择,只需np.random.randint(0,a.size),除非我认为需要许多互斥的选择。
          • @askwchan,对!我在想什么。 np.random.randint(0,a.size, size=size_you_want) 就足够了。
          • @CT Zhu: 我得到一个 AttributeError: 'list' object has no attribute 'size'
          • 哦,a 是一个列表,而不是 array。首先将其转换为array。我忘了复制 1 行。
          • @askwchan,哦,不。你的方法总是会变成带替换的采样。 HappyPy 确实需要 replace=False,因此一旦对元素进行采样,它将不会再次采样。
          【解决方案7】:

          根据您的评论:

          样本已经是a。我想直接使用a,这样我就可以控制还剩下多少元素并使用a 执行其他操作。 – 快乐派

          在删除 n 随机选择的元素后,您似乎对使用 a 感兴趣。相反,为什么不使用N = len(a) - na 中随机选择的元素呢?由于您希望它们仍保持原始顺序,因此您可以从@CTZhu 的答案中的索引中进行选择,然后对它们进行排序并从原始列表中获取:

          import numpy as np
          n = 3 #number to 'remove'
          a = np.array([1,4,1,3,3,2,1,4])
          i = np.random.choice(np.arange(a.size), a.size-n, replace=False)
          i.sort()
          a[i]
          #array([1, 4, 1, 3, 1])
          

          所以现在您可以再次将其另存为a

          a = a[i]
          

          并使用 a 删除 n 元素。

          【讨论】:

            【解决方案8】:

            这是找出随机选择元素的索引的一种方法:

            import random # plain random module, not numpy's
            random.choice(list(enumerate(a)))[0]
            => 4      # just an example, index is 4
            

            或者您可以在一个步骤中检索元素索引:

            random.choice(list(enumerate(a)))
            => (1, 4) # just an example, index is 1 and element is 4
            

            【讨论】:

            • 这对我不起作用。它给了我一个“ValueError:a must be 1-dimensional”
            • 我复制/粘贴了您的代码和上面的列表,但仍然出现相同的错误。它对你有用吗?
            • list(enumerate(a)) 产生一个元组列表,它被认为是一个二维数组对象。这行不通。
            • @HappyPy 你是对的,我用random.choice 测试了它,而不是np.random.choice。如果您必须绝对使用np.random.choice,那么我的答案将不起作用,我将其删除。但是,如果您使用普通的旧 random.choice(来自 random 模块),它会起作用。
            • 强烈警告,这将有糟糕的表现,这是人们首先使用 numpy 的主要原因之一。您正在遍历整个数组。只生成一个介于 0 和列表长度之间的随机整数会比这个更便宜。
            猜你喜欢
            • 1970-01-01
            • 2020-11-14
            • 1970-01-01
            • 2015-01-24
            • 1970-01-01
            • 2018-11-18
            • 2021-06-16
            • 2014-06-06
            • 1970-01-01
            相关资源
            最近更新 更多