代码之家  ›  专栏  ›  技术社区  ›  robintw

从numpy数组中随机选择单元格-不替换

  •  13
  • robintw  · 技术社区  · 14 年前

    我在numpy中编写了一些建模程序,需要从numpy数组中随机选择单元格并对其进行一些处理。必须选择所有单元格而不替换(如中所示,一旦选择了单元格,就不能再选择它,但所有单元格都必须在末尾选择)。

    我正在从IDL过渡,在那里我可以找到一个很好的方法来完成这项工作,但我认为numpy也有一个很好的方法来完成这项工作。你有什么建议?

    更新: 我应该声明我正在尝试在二维数组上执行此操作,因此要返回一组二维索引。

    6 回复  |  直到 7 年前
        1
  •  20
  •   Wolph    14 年前

    如何使用 numpy.random.shuffle numpy.random.permutation 如果仍然需要原始数组?

    如果需要就地更改数组,则可以创建这样的索引数组:

    your_array = <some numpy array>
    index_array = numpy.arange(your_array.size)
    numpy.random.shuffle(index_array)
    
    print your_array[index_array[:10]]
    
        2
  •  3
  •   Richard    11 年前

    所有这些答案对我来说都有点费解。

    我假设您有一个多维数组,从中可以生成一个详尽的索引列表。您希望对这些索引进行无序排列,这样就可以以随机顺序访问每个数组元素。

    下面的代码将以一种简单而直接的方式执行此操作:

    #!/usr/bin/python
    import numpy as np
    
    #Define a two-dimensional array
    #Use any number of dimensions, and dimensions of any size
    d=numpy.zeros(30).reshape((5,6))
    
    #Get a list of indices for an array of this shape
    indices=list(np.ndindex(d.shape))
    
    #Shuffle the indices in-place
    np.random.shuffle(indices)
    
    #Access array elements using the indices to do cool stuff
    for i in indices:
      d[i]=5
    
    print d
    

    印刷 d 已验证是否已访问所有元素。

    请注意,数组可以有任意数量的维度,并且维度可以有任意大小。

    这种方法的唯一缺点是 D 那么大 indices 可能会变得相当大。因此,最好有一个 发电机 . 遗憾的是,我想不出如何手工构建一个无序的迭代器。

        3
  •  2
  •   Community SushiHangover    7 年前

    从@ WoLpH

    对于二维数组,我认为它将取决于您想要或需要了解的关于索引的内容。

    你可以这样做:

    data = np.arange(25).reshape((5,5))
    
    x, y  = np.where( a = a)
    idx = zip(x,y)
    np.random.shuffle(idx)
    

    data = np.arange(25).reshape((5,5))
    
    grid = np.indices(data.shape)
    idx = zip( grid[0].ravel(), grid[1].ravel() )
    np.random.shuffle(idx)
    

    然后你可以使用列表 idx 根据需要迭代随机排列的二维数组索引,并从 data 保持不变。

    注释 :您还可以通过 itertools.product 同样,以防您对这套工具更满意。

        4
  •  1
  •   denis    14 年前

    使用 random.sample 在0中生成int。A.尺寸无重复, 然后将它们拆分为索引对:

    import random
    import numpy as np
    
    def randint2_nodup( nsample, A ):
        """ uniform int pairs, no dups:
            r = randint2_nodup( nsample, A )
            A[r]
            for jk in zip(*r):
                ... A[jk]
        """
        assert A.ndim == 2
        sample = np.array( random.sample( xrange( A.size ), nsample ))  # nodup ints
        return sample // A.shape[1], sample % A.shape[1]  # pairs
    
    
    if __name__ == "__main__":
        import sys
    
        nsample = 8
        ncol = 5
        exec "\n".join( sys.argv[1:] )  # run this.py N= ...
        A = np.arange( 0, 2*ncol ).reshape((2,ncol))
    
        r = randint2_nodup( nsample, A )
        print "r:", r
        print "A[r]:", A[r]
        for jk in zip(*r):
            print jk, A[jk]
    
        5
  •  1
  •   dan mackinlay    13 年前

    假设您有一个8x3大小的数据点数组

    data = np.arange(50,74).reshape(8,-1)
    

    如果你真的想要像你所说的那样对所有的索引进行采样,那么我能想到的最紧凑的方法是:

    #generate a permutation of data's size, coerced to data's shape
    idxs = divmod(np.random.permutation(data.size),data.shape[1])
    
    #iterate over it
    for x,y in zip(*idxs): 
        #do something to data[x,y] here
        pass
    

    但是,MOE通常不需要简单地将二维数组作为二维数组来访问它们,在这种情况下,可以更加紧凑。只需在数组上创建一个1d视图,并保存一些索引争论。

    flat_data = data.ravel()
    flat_idxs = np.random.permutation(flat_data.size)
    for i in flat_idxs:
        #do something to flat_data[i] here
        pass
    

    这仍然会按您的需要排列二维“原始”数组。要查看此信息,请尝试:

     flat_data[12] = 1000000
     print data[4,0]
     #returns 1000000
    
        6
  •  1
  •   ajeje    11 年前

    使用numpy 1.7或更高版本的用户也可以使用内置函数 numpy.random.choice