【问题标题】:Numpy: Get random set of rows from 2D arrayNumpy:从二维数组中获取随机行集
【发布时间】:2012-12-25 02:52:23
【问题描述】:

我有一个非常大的二维数组,看起来像这样:

a=
[[a1, b1, c1],
 [a2, b2, c2],
 ...,
 [an, bn, cn]]

使用 numpy,有没有一种简单的方法可以从初始数组 a 中获取一个新的二维数组,例如 2 个随机行(无需替换)?

例如

b=
[[a4,  b4,  c4],
 [a99, b99, c99]]

【问题讨论】:

  • 有一个问题可以替换而一个没有问题是愚蠢的,您应该只允许两个答案,实际上鼓励两个答案。

标签: python numpy


【解决方案1】:

可以使用随机数生成器从给定数组生成随机样本:

rng = np.random.default_rng()
b = rng.choice(a, 2, replace=False)
b
>>> [[a4,  b4,  c4],
    [a99, b99, c99]]

【讨论】:

    【解决方案2】:

    这与 Hezi Rasheff 提供的答案相似,但经过简化,以便新的 python 用户了解发生了什么(我注意到许多新的数据科学学生以最奇怪的方式获取随机样本,因为他们不知道自己在做什么蟒蛇)。

    您可以使用以下方法从数组中获取多个随机索引:

    indices = np.random.choice(A.shape[0], number_of_samples, replace=False)
    

    然后,您可以对 numpy 数组使用精美的索引来获取这些索引处的样本:

    A[indices]
    

    这将从您的数据中获得指定数量的随机样本。

    【讨论】:

    • 似乎是最好的解决方案,应该是选择的答案。 “然后你可以使用切片”,错字:fancy indexing.
    • @mins “花式索引”确实是正确的术语,而不是“切片”。我解决了这个问题。谢谢。
    【解决方案3】:

    另一种方法是使用Generator 类的choice 方法https://github.com/numpy/numpy/issues/10835

    import numpy as np
    
    # generate the random array
    A = np.random.randint(5, size=(10,3))
    
    # use the choice method of the Generator class
    rng = np.random.default_rng()
    A_sampled = rng.choice(A, 2)
    

    导致采样数据,

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

    运行时间也分析如下,

    %timeit rng.choice(A, 2)
    15.1 µs ± 115 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    
    %timeit np.random.permutation(A)[:2]
    4.22 µs ± 83.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    
    %timeit A[np.random.randint(A.shape[0], size=2), :]
    10.6 µs ± 418 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    

    但是当数组变大时,A = np.random.randint(10, size=(1000,300))。处理索引是最好的方法。

    %timeit A[np.random.randint(A.shape[0], size=50), :]
    17.6 µs ± 657 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    
    %timeit rng.choice(A, 50)
    22.3 µs ± 134 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    %timeit np.random.permutation(A)[:50]
    143 µs ± 1.33 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    因此,permutation 方法似乎在您的数组较小时是最有效的方法,而在您的数组较大时处理索引是最佳解决方案。

    【讨论】:

      【解决方案4】:

      如果您想生成多个随机的行子集,例如,如果您正在执行 RANSAC。

      num_pop = 10
      num_samples = 2
      pop_in_sample = 3
      rows_to_sample = np.random.random([num_pop, 5])
      random_numbers = np.random.random([num_samples, num_pop])
      samples = np.argsort(random_numbers, axis=1)[:, :pop_in_sample]
      # will be shape [num_samples, pop_in_sample, 5]
      row_subsets = rows_to_sample[samples, :]
      

      【讨论】:

        【解决方案5】:

        我看到有人建议排列。其实可以做成一行:

        >>> A = np.random.randint(5, size=(10,3))
        >>> np.random.permutation(A)[:2]
        
        array([[0, 3, 0],
               [3, 1, 2]])
        

        【讨论】:

          【解决方案6】:

          如果您需要相同的行但只是随机样本,那么,

          import random
          new_array = random.sample(old_array,x)
          

          这里的 x 必须是一个 'int',定义了你想要随机选择的行数。

          【讨论】:

          【解决方案7】:

          这是一篇旧帖子,但这是最适合我的:

          A[np.random.choice(A.shape[0], num_rows_2_sample, replace=False)]
          

          将 replace=False 更改为 True 以获得相同的结果,但需要替换。

          【讨论】:

          • @SalvadorDali 我已经编辑了 Hezi 的帖子以不选择替换。编辑经过同行评审后,您会看到将 replace=False 参数添加到 choice
          • @SalvadorDali 为什么不呢?
          【解决方案8】:
          >>> A = np.random.randint(5, size=(10,3))
          >>> A
          array([[1, 3, 0],
                 [3, 2, 0],
                 [0, 2, 1],
                 [1, 1, 4],
                 [3, 2, 2],
                 [0, 1, 0],
                 [1, 3, 1],
                 [0, 4, 1],
                 [2, 4, 2],
                 [3, 3, 1]])
          >>> idx = np.random.randint(10, size=2)
          >>> idx
          array([7, 6])
          >>> A[idx,:]
          array([[0, 4, 1],
                 [1, 3, 1]])
          

          把它放在一个一般情况下:

          A[np.random.randint(A.shape[0], size=2), :]
          

          对于非替换(numpy 1.7.0+):

          A[np.random.choice(A.shape[0], 2, replace=False), :]
          

          我不相信在 1.7 之前有一种无需替换即可生成随机列表的好方法。也许您可以设置一个小定义,确保两个值不相同。

          【讨论】:

          • 也许没有什么好办法,但有一个和np.random.choice一样好的办法,那就是np.random.permutation(A.shape[0])[:2],其实不是很好,但这就是np.random.choice时间...或者如果您不想就地更改阵列,np.random.shuffle
          • 在numpy 1.7之前,使用random.sample(xrange(10), 2)
          • 你为什么要命名你的变量 A 和 B 之类的?它使阅读变得更加困难。
          • @CharlieParker 是吗?矩阵通常用单个大写字母表示。
          • 不需要沿第二个轴进行冒号切片(不需要[..., ])。
          【解决方案9】:

          如果您只想按某个因素对数据进行下采样,另一种选择是创建一个随机掩码。假设我想将原始数据集下采样到 25%,该数据集当前保存在数组 data_arr 中:

          # generate random boolean mask the length of data
          # use p 0.75 for False and 0.25 for True
          mask = numpy.random.choice([False, True], len(data_arr), p=[0.75, 0.25])
          

          现在您可以调用 data_arr[mask] 并返回大约 25% 的行,随机抽样。

          【讨论】:

          • 如果您不想更换样品,可以添加replace = False
          • @Sarah Replacement 对于这种采样方法来说不是问题,因为data_arr 中的每个位置都会返回一个真/假值。在我的示例中,随机约 25% 的位置将是 True,这些位置是从 data_arr 采样的。
          • 你是对的。我们不需要replace=False。正如您所指出的,采样的记录数只是近似值,而不是精确的。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-11
          • 2018-06-07
          相关资源
          最近更新 更多