numpy 独立按行随机洗牌
numpy random shuffle by row independently
我有以下数组:
a= array([[ 1, 2, 3],
[ 1, 2, 3],
[ 1, 2, 3])
我知道 np.random,shuffle(a.T)
会沿行打乱数组,但我需要的是独立打乱每一行。这怎么能在 numpy 中完成?速度很关键,因为会有几百万行。
对于这个特定问题,每一行将包含相同的起始人口。
import numpy as np
np.random.seed(2018)
def scramble(a, axis=-1):
"""
Return an array with the values of `a` independently shuffled along the
given axis
"""
b = a.swapaxes(axis, -1)
n = a.shape[axis]
idx = np.random.choice(n, n, replace=False)
b = b[..., idx]
return b.swapaxes(axis, -1)
a = a = np.arange(4*9).reshape(4, 9)
# array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8],
# [ 9, 10, 11, 12, 13, 14, 15, 16, 17],
# [18, 19, 20, 21, 22, 23, 24, 25, 26],
# [27, 28, 29, 30, 31, 32, 33, 34, 35]])
print(scramble(a, axis=1))
产量
[[ 3 8 7 0 4 5 1 2 6]
[12 17 16 9 13 14 10 11 15]
[21 26 25 18 22 23 19 20 24]
[30 35 34 27 31 32 28 29 33]]
同时沿 0 轴加扰:
print(scramble(a, axis=0))
产量
[[18 19 20 21 22 23 24 25 26]
[ 0 1 2 3 4 5 6 7 8]
[27 28 29 30 31 32 33 34 35]
[ 9 10 11 12 13 14 15 16 17]]
首先将目标轴与最后一个轴交换:
b = a.swapaxes(axis, -1)
这是一种常用技巧,用于标准化处理单轴的代码。
它将一般情况简化为处理最后一个轴的特定情况。
由于在 NumPy 版本 1.10 或更高版本中 swapaxes
return 是一个视图,因此不涉及复制,因此调用 swapaxes
非常快。
现在我们可以为最后一个轴生成一个新的索引顺序:
n = a.shape[axis]
idx = np.random.choice(n, n, replace=False)
现在我们可以洗牌 b
(独立地沿着最后一个轴):
b = b[..., idx]
然后将swapaxes
反转为return一个a
形的结果:
return b.swapaxes(axis, -1)
上面的回答很好。但我会以一种快速而肮脏的方式抛出:
a = np.array([[1,2,3], [1,2,3], [1,2,3]])
ignore_list_outpput = [np.random.shuffle(x) for x in a]
Then, a can be something like this
array([[2, 1, 3],
[4, 6, 5],
[9, 7, 8]])
不是很优雅,但是你可以用短短一行就可以完成这项工作。
如果您不想要 return
值并想直接对数组进行操作,您可以指定要打乱的索引。
>>> import numpy as np
>>>
>>>
>>> a = np.array([[1,2,3], [1,2,3], [1,2,3]])
>>>
>>> # Shuffle row `2` independently
>>> np.random.shuffle(a[2])
>>> a
array([[1, 2, 3],
[1, 2, 3],
[3, 2, 1]])
>>>
>>> # Shuffle column `0` independently
>>> np.random.shuffle(a[:,0])
>>> a
array([[3, 2, 3],
[1, 2, 3],
[1, 2, 1]])
如果您还想要 return 值,可以使用 numpy.random.permutation
,在这种情况下,将 np.random.shuffle(a[n])
替换为 a[n] = np.random.permutation(a[n])
。
警告,请勿执行a[n] = np.random.shuffle(a[n])
。 shuffle
没有 return
任何东西,所以你最终 "shuffling" 的 row/column 将被 nan
代替。
根据我对@Hun 的回答的评论,这里是最快的方法:
def shuffle_along(X):
"""Minimal in place independent-row shuffler."""
[np.random.shuffle(x) for x in X]
这就地工作并且只能随机排列行。如果您需要更多选择:
def shuffle_along(X, axis=0, inline=False):
"""More elaborate version of the above."""
if not inline:
X = X.copy()
if axis == 0:
[np.random.shuffle(x) for x in X]
if axis == 1:
[np.random.shuffle(x) for x in X.T]
if not inline:
return X
然而,这具有仅适用于二维数组的局限性。对于高维张量,我会使用:
def shuffle_along(X, axis=0, inline=True):
"""Shuffle along any axis of a tensor."""
if not inline:
X = X.copy()
np.apply_along_axis(np.random.shuffle, axis, X) # <-- I just changed this
if not inline:
return X
您可以使用 numpy 完成它,无需任何循环或额外函数,而且速度更快。例如,我们有一个大小为 (2, 6) 的数组,我们想要一个子数组 (2,2),每个列都有独立的随机索引。
import numpy as np
test = np.array([[1, 1],
[2, 2],
[0.5, 0.5],
[0.3, 0.3],
[4, 4],
[7, 7]])
id_rnd = np.random.randint(6, size=(2, 2)) # select random numbers, use choice and range if don want replacement.
new = np.take_along_axis(test, id_rnd, axis=0)
Out:
array([[2. , 2. ],
[0.5, 2. ]])
它适用于任意数量的维度。
我有以下数组:
a= array([[ 1, 2, 3],
[ 1, 2, 3],
[ 1, 2, 3])
我知道 np.random,shuffle(a.T)
会沿行打乱数组,但我需要的是独立打乱每一行。这怎么能在 numpy 中完成?速度很关键,因为会有几百万行。
对于这个特定问题,每一行将包含相同的起始人口。
import numpy as np
np.random.seed(2018)
def scramble(a, axis=-1):
"""
Return an array with the values of `a` independently shuffled along the
given axis
"""
b = a.swapaxes(axis, -1)
n = a.shape[axis]
idx = np.random.choice(n, n, replace=False)
b = b[..., idx]
return b.swapaxes(axis, -1)
a = a = np.arange(4*9).reshape(4, 9)
# array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8],
# [ 9, 10, 11, 12, 13, 14, 15, 16, 17],
# [18, 19, 20, 21, 22, 23, 24, 25, 26],
# [27, 28, 29, 30, 31, 32, 33, 34, 35]])
print(scramble(a, axis=1))
产量
[[ 3 8 7 0 4 5 1 2 6]
[12 17 16 9 13 14 10 11 15]
[21 26 25 18 22 23 19 20 24]
[30 35 34 27 31 32 28 29 33]]
同时沿 0 轴加扰:
print(scramble(a, axis=0))
产量
[[18 19 20 21 22 23 24 25 26]
[ 0 1 2 3 4 5 6 7 8]
[27 28 29 30 31 32 33 34 35]
[ 9 10 11 12 13 14 15 16 17]]
首先将目标轴与最后一个轴交换:
b = a.swapaxes(axis, -1)
这是一种常用技巧,用于标准化处理单轴的代码。
它将一般情况简化为处理最后一个轴的特定情况。
由于在 NumPy 版本 1.10 或更高版本中 swapaxes
return 是一个视图,因此不涉及复制,因此调用 swapaxes
非常快。
现在我们可以为最后一个轴生成一个新的索引顺序:
n = a.shape[axis]
idx = np.random.choice(n, n, replace=False)
现在我们可以洗牌 b
(独立地沿着最后一个轴):
b = b[..., idx]
然后将swapaxes
反转为return一个a
形的结果:
return b.swapaxes(axis, -1)
上面的回答很好。但我会以一种快速而肮脏的方式抛出:
a = np.array([[1,2,3], [1,2,3], [1,2,3]])
ignore_list_outpput = [np.random.shuffle(x) for x in a]
Then, a can be something like this
array([[2, 1, 3],
[4, 6, 5],
[9, 7, 8]])
不是很优雅,但是你可以用短短一行就可以完成这项工作。
如果您不想要 return
值并想直接对数组进行操作,您可以指定要打乱的索引。
>>> import numpy as np
>>>
>>>
>>> a = np.array([[1,2,3], [1,2,3], [1,2,3]])
>>>
>>> # Shuffle row `2` independently
>>> np.random.shuffle(a[2])
>>> a
array([[1, 2, 3],
[1, 2, 3],
[3, 2, 1]])
>>>
>>> # Shuffle column `0` independently
>>> np.random.shuffle(a[:,0])
>>> a
array([[3, 2, 3],
[1, 2, 3],
[1, 2, 1]])
如果您还想要 return 值,可以使用 numpy.random.permutation
,在这种情况下,将 np.random.shuffle(a[n])
替换为 a[n] = np.random.permutation(a[n])
。
警告,请勿执行a[n] = np.random.shuffle(a[n])
。 shuffle
没有 return
任何东西,所以你最终 "shuffling" 的 row/column 将被 nan
代替。
根据我对@Hun 的回答的评论,这里是最快的方法:
def shuffle_along(X):
"""Minimal in place independent-row shuffler."""
[np.random.shuffle(x) for x in X]
这就地工作并且只能随机排列行。如果您需要更多选择:
def shuffle_along(X, axis=0, inline=False):
"""More elaborate version of the above."""
if not inline:
X = X.copy()
if axis == 0:
[np.random.shuffle(x) for x in X]
if axis == 1:
[np.random.shuffle(x) for x in X.T]
if not inline:
return X
然而,这具有仅适用于二维数组的局限性。对于高维张量,我会使用:
def shuffle_along(X, axis=0, inline=True):
"""Shuffle along any axis of a tensor."""
if not inline:
X = X.copy()
np.apply_along_axis(np.random.shuffle, axis, X) # <-- I just changed this
if not inline:
return X
您可以使用 numpy 完成它,无需任何循环或额外函数,而且速度更快。例如,我们有一个大小为 (2, 6) 的数组,我们想要一个子数组 (2,2),每个列都有独立的随机索引。
import numpy as np
test = np.array([[1, 1],
[2, 2],
[0.5, 0.5],
[0.3, 0.3],
[4, 4],
[7, 7]])
id_rnd = np.random.randint(6, size=(2, 2)) # select random numbers, use choice and range if don want replacement.
new = np.take_along_axis(test, id_rnd, axis=0)
Out:
array([[2. , 2. ],
[0.5, 2. ]])
它适用于任意数量的维度。