Select 来自 3D numpy 数组的 N 个随机行
Select N random rows from a 3D numpy array
我有一个 3D 数组,我想从轴 1 随机 'sets'(注意:不是 pythonic 集)N 次。我可以通过嵌套的 For 循环来实现这一点,但我至少需要这样做 10000 次,所以如果可能的话,我需要找到一个向量化的解决方案。
我将尝试用一个例子来解释这一点。如果我想检索 N 组数据,我想 select 我的 3D 数组中轴 1 的一个随机索引,对于轴 0 中的每个元素。例如在我的 N 组中的第一个中,我随机 select 索引 [0, 2, 1]
,这与三个不同的数组位置相关:分别为 [0, 0, :]
、[1, 2, :]
和 [2, 1, :]
(即轴 0 每次递增 1,轴 1 基于随机 selected 索引)。
下面是伪代码中的数值示例:
# Create some arbitrary data (EDIT: based on mozway's answer)
a = array([[[ 0. , 4. , 8. , 12. , 16. , 20. , 24. ],
[ 1. , 5. , 9. , 13. , 17. , 21. , 25. ],
[ 2. , 6. , 10. , 14. , 18. , 22. , 26. ],
[ 3. , 7. , 11. , 15. , 19. , 23. , 27. ]],
[[ 0.1, 4.1, 8.1, 12.1, 16.1, 20.1, 24.1],
[ 1.1, 5.1, 9.1, 13.1, 17.1, 21.1, 25.1],
[ 2.1, 6.1, 10.1, 14.1, 18.1, 22.1, 26.1],
[ 3.1, 7.1, 11.1, 15.1, 19.1, 23.1, 27.1]],
[[ 0.2, 4.2, 8.2, 12.2, 16.2, 20.2, 24.2],
[ 1.2, 5.2, 9.2, 13.2, 17.2, 21.2, 25.2],
[ 2.2, 6.2, 10.2, 14.2, 18.2, 22.2, 26.2],
[ 3.2, 7.2, 11.2, 15.2, 19.2, 23.2, 27.2]]])
# Define the number of requested sets
N = 2
# Define the chosen data per 'set' (normally would be random)
idx = [[0, 2, 1], [1, 3, 3]]
# First set would give (with choices [0, 2, 1]):
arr = [[ 0. , 4. , 8. , 12. , 16. , 20. , 24. ],
[ 2.1, 6.1, 10.1, 14.1, 18.1, 22.1, 26.1],
[ 1.2, 5.2, 9.2 , 13.2, 17.2, 21.2, 25.2]]
# Second set would give (with choices [1, 3, 3]):
arr = [[ 1. , 5. , 9. , 13. , 17. , 21. , 25. ],
[ 3.1, 7.1, 11.1, 15.1, 19.1, 23.1, 27.1],
[ 3.2, 7.2, 11.2, 15.2, 19.2, 23.2, 27.2]]
# So, the final output would combine all sets:
arr = [[[ 0. , 4. , 8. , 12. , 16. , 20. , 24. ],
[ 2.1, 6.1, 10.1, 14.1, 18.1, 22.1, 26.1],
[ 1.2, 5.2, 9.2 , 13.2, 17.2, 21.2, 25.2]],
[ 1. , 5. , 9. , 13. , 17. , 21. , 25. ],
[ 3.1, 7.1, 11.1, 15.1, 19.1, 23.1, 27.1],
[ 3.2, 7.2, 11.2, 15.2, 19.2, 23.2, 27.2]]]
澄清问题前的原始答案,参见独立抽样
您可以获得随机索引和切片:
N = 2
# get random indices on the first dimension
idx = np.random.choice(np.arange(x.shape[0]), size=N)
# slice
x[idx]
示例输出(形状:(2, 3, 7)):
array([[[ 1, 2, 5, 10, 17, 26, 37],
[ 2, 3, 6, 11, 18, 27, 38],
[ 3, 4, 7, 12, 19, 28, 39],
[ 4, 5, 8, 13, 20, 29, 40]],
[[ 1, 2, 3, 4, 5, 6, 7],
[ 2, 3, 4, 5, 6, 7, 8],
[ 3, 4, 5, 6, 7, 8, 9],
[ 4, 5, 6, 7, 8, 9, 10]]])
其他维度的示例:
# second dimension (axis 1)
idx = np.random.choice(np.arange(x.shape[1]), size=N)
x[:, idx]
考虑到您的问题的澄清,您想要 select 轴 1(第二维)上的 3D 数组中的 N 个随机行,但独立于轴 0:
我们将 a 称为数组,将 x、y、z 称为其 3 个维度。
一个简单的方法是 select N*x 个随机索引,这样每个 x 就有 N 个。然后在前 2 个维度上展平数组并切片。
示例输入(注意 x/x.1/x.2 以跟踪原始维度):
array([[[ 0. , 4. , 8. , 12. , 16. , 20. , 24. ],
[ 1. , 5. , 9. , 13. , 17. , 21. , 25. ],
[ 2. , 6. , 10. , 14. , 18. , 22. , 26. ],
[ 3. , 7. , 11. , 15. , 19. , 23. , 27. ]],
[[ 0.1, 4.1, 8.1, 12.1, 16.1, 20.1, 24.1],
[ 1.1, 5.1, 9.1, 13.1, 17.1, 21.1, 25.1],
[ 2.1, 6.1, 10.1, 14.1, 18.1, 22.1, 26.1],
[ 3.1, 7.1, 11.1, 15.1, 19.1, 23.1, 27.1]],
[[ 0.2, 4.2, 8.2, 12.2, 16.2, 20.2, 24.2],
[ 1.2, 5.2, 9.2, 13.2, 17.2, 21.2, 25.2],
[ 2.2, 6.2, 10.2, 14.2, 18.2, 22.2, 26.2],
[ 3.2, 7.2, 11.2, 15.2, 19.2, 23.2, 27.2]]])
处理中:
N = 2
# sample with repeats
idx = np.random.randint(y, size=N*x)
corr = np.repeat(np.arange(0,(x-1)*y+1, y), N)
idx += corr
# sample without repeats
idx = np.concatenate([np.random.choice(list(range(y)), replace=False, size=N)+(i*y) for i in range(x)])
# slice array
a.reshape(x*y,z)[idx].reshape(x,N,z).swapaxes(0,1)
可能的输出 (N,x,z) 形状:
array([[[ 0. , 4. , 8. , 12. , 16. , 20. , 24. ],
[ 1.1, 5.1, 9.1, 13.1, 17.1, 21.1, 25.1],
[ 0.2, 4.2, 8.2, 12.2, 16.2, 20.2, 24.2]],
[[ 3. , 7. , 11. , 15. , 19. , 23. , 27. ],
[ 3.1, 7.1, 11.1, 15.1, 19.1, 23.1, 27.1],
[ 1.2, 5.2, 9.2, 13.2, 17.2, 21.2, 25.2]]])
我有一个 3D 数组,我想从轴 1 随机 'sets'(注意:不是 pythonic 集)N 次。我可以通过嵌套的 For 循环来实现这一点,但我至少需要这样做 10000 次,所以如果可能的话,我需要找到一个向量化的解决方案。
我将尝试用一个例子来解释这一点。如果我想检索 N 组数据,我想 select 我的 3D 数组中轴 1 的一个随机索引,对于轴 0 中的每个元素。例如在我的 N 组中的第一个中,我随机 select 索引 [0, 2, 1]
,这与三个不同的数组位置相关:分别为 [0, 0, :]
、[1, 2, :]
和 [2, 1, :]
(即轴 0 每次递增 1,轴 1 基于随机 selected 索引)。
下面是伪代码中的数值示例:
# Create some arbitrary data (EDIT: based on mozway's answer)
a = array([[[ 0. , 4. , 8. , 12. , 16. , 20. , 24. ],
[ 1. , 5. , 9. , 13. , 17. , 21. , 25. ],
[ 2. , 6. , 10. , 14. , 18. , 22. , 26. ],
[ 3. , 7. , 11. , 15. , 19. , 23. , 27. ]],
[[ 0.1, 4.1, 8.1, 12.1, 16.1, 20.1, 24.1],
[ 1.1, 5.1, 9.1, 13.1, 17.1, 21.1, 25.1],
[ 2.1, 6.1, 10.1, 14.1, 18.1, 22.1, 26.1],
[ 3.1, 7.1, 11.1, 15.1, 19.1, 23.1, 27.1]],
[[ 0.2, 4.2, 8.2, 12.2, 16.2, 20.2, 24.2],
[ 1.2, 5.2, 9.2, 13.2, 17.2, 21.2, 25.2],
[ 2.2, 6.2, 10.2, 14.2, 18.2, 22.2, 26.2],
[ 3.2, 7.2, 11.2, 15.2, 19.2, 23.2, 27.2]]])
# Define the number of requested sets
N = 2
# Define the chosen data per 'set' (normally would be random)
idx = [[0, 2, 1], [1, 3, 3]]
# First set would give (with choices [0, 2, 1]):
arr = [[ 0. , 4. , 8. , 12. , 16. , 20. , 24. ],
[ 2.1, 6.1, 10.1, 14.1, 18.1, 22.1, 26.1],
[ 1.2, 5.2, 9.2 , 13.2, 17.2, 21.2, 25.2]]
# Second set would give (with choices [1, 3, 3]):
arr = [[ 1. , 5. , 9. , 13. , 17. , 21. , 25. ],
[ 3.1, 7.1, 11.1, 15.1, 19.1, 23.1, 27.1],
[ 3.2, 7.2, 11.2, 15.2, 19.2, 23.2, 27.2]]
# So, the final output would combine all sets:
arr = [[[ 0. , 4. , 8. , 12. , 16. , 20. , 24. ],
[ 2.1, 6.1, 10.1, 14.1, 18.1, 22.1, 26.1],
[ 1.2, 5.2, 9.2 , 13.2, 17.2, 21.2, 25.2]],
[ 1. , 5. , 9. , 13. , 17. , 21. , 25. ],
[ 3.1, 7.1, 11.1, 15.1, 19.1, 23.1, 27.1],
[ 3.2, 7.2, 11.2, 15.2, 19.2, 23.2, 27.2]]]
澄清问题前的原始答案,参见独立抽样
您可以获得随机索引和切片:
N = 2
# get random indices on the first dimension
idx = np.random.choice(np.arange(x.shape[0]), size=N)
# slice
x[idx]
示例输出(形状:(2, 3, 7)):
array([[[ 1, 2, 5, 10, 17, 26, 37],
[ 2, 3, 6, 11, 18, 27, 38],
[ 3, 4, 7, 12, 19, 28, 39],
[ 4, 5, 8, 13, 20, 29, 40]],
[[ 1, 2, 3, 4, 5, 6, 7],
[ 2, 3, 4, 5, 6, 7, 8],
[ 3, 4, 5, 6, 7, 8, 9],
[ 4, 5, 6, 7, 8, 9, 10]]])
其他维度的示例:
# second dimension (axis 1)
idx = np.random.choice(np.arange(x.shape[1]), size=N)
x[:, idx]
考虑到您的问题的澄清,您想要 select 轴 1(第二维)上的 3D 数组中的 N 个随机行,但独立于轴 0:
我们将 a 称为数组,将 x、y、z 称为其 3 个维度。
一个简单的方法是 select N*x 个随机索引,这样每个 x 就有 N 个。然后在前 2 个维度上展平数组并切片。
示例输入(注意 x/x.1/x.2 以跟踪原始维度):
array([[[ 0. , 4. , 8. , 12. , 16. , 20. , 24. ],
[ 1. , 5. , 9. , 13. , 17. , 21. , 25. ],
[ 2. , 6. , 10. , 14. , 18. , 22. , 26. ],
[ 3. , 7. , 11. , 15. , 19. , 23. , 27. ]],
[[ 0.1, 4.1, 8.1, 12.1, 16.1, 20.1, 24.1],
[ 1.1, 5.1, 9.1, 13.1, 17.1, 21.1, 25.1],
[ 2.1, 6.1, 10.1, 14.1, 18.1, 22.1, 26.1],
[ 3.1, 7.1, 11.1, 15.1, 19.1, 23.1, 27.1]],
[[ 0.2, 4.2, 8.2, 12.2, 16.2, 20.2, 24.2],
[ 1.2, 5.2, 9.2, 13.2, 17.2, 21.2, 25.2],
[ 2.2, 6.2, 10.2, 14.2, 18.2, 22.2, 26.2],
[ 3.2, 7.2, 11.2, 15.2, 19.2, 23.2, 27.2]]])
处理中:
N = 2
# sample with repeats
idx = np.random.randint(y, size=N*x)
corr = np.repeat(np.arange(0,(x-1)*y+1, y), N)
idx += corr
# sample without repeats
idx = np.concatenate([np.random.choice(list(range(y)), replace=False, size=N)+(i*y) for i in range(x)])
# slice array
a.reshape(x*y,z)[idx].reshape(x,N,z).swapaxes(0,1)
可能的输出 (N,x,z) 形状:
array([[[ 0. , 4. , 8. , 12. , 16. , 20. , 24. ],
[ 1.1, 5.1, 9.1, 13.1, 17.1, 21.1, 25.1],
[ 0.2, 4.2, 8.2, 12.2, 16.2, 20.2, 24.2]],
[[ 3. , 7. , 11. , 15. , 19. , 23. , 27. ],
[ 3.1, 7.1, 11.1, 15.1, 19.1, 23.1, 27.1],
[ 1.2, 5.2, 9.2, 13.2, 17.2, 21.2, 25.2]]])