我需要一一打乱 numpy 矩阵的所有列。这是我当前的代码
n, p = X.shape
val = []
for i in range(p):
Xt = X.copy()
np.random.shuffle(Xt[:, i])
print(Xt)
我每次X
复制到变量Xt
.这似乎效率很低。
如何加快此代码的速度?
编辑:示例鉴于
`X= [[0 3 6]
[1 4 7]
[2 5 8]]`
for 循环的预期输出为:
>>> [[2 3 6]
[1 4 7]
[0 5 8]]
[[0 5 6]
[1 4 7]
[2 3 8]]
[[0 3 7]
[1 4 8]
[2 5 6]]
>>>
每次只应随机播放一列。所有其他列应具有与原始矩阵相同的值
在 numpy 中打乱列可以就地完成,根本不需要复制:
import numpy as np
X = np.arange(25).reshape(5,5).transpose()
print X
np.random.shuffle(X[:,2]) # here, X[:,2] is a just a view onto this column of X
print X
输出为:
[[ 0 1 2 3 4] # the original
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]
[[ 0 1 2 3 4] # note that the middle column is shuffled here
[ 5 6 12 8 9]
[10 11 22 13 14]
[15 16 17 18 19]
[20 21 7 23 24]]
您正在做大量复制,很难判断其中是否有任何需要满足您的整体需求,但对于随机播放来说不是必需的。
编辑:
虽然这个问题是用洗牌来写的,因为洗牌可以就地完成,所以实际的低效率是由于复制。 因此,问题变成了OP在副本方面需要什么? 由于需要恢复原始数组,因此需要复制或复制一些其他索引或数组值。 在这种情况下,唯一的效率是希望不需要为每个周期复制整个数组,而只需要复制列(或者,基本上等价地复制整个矩阵一次 - 与复制矩阵 p 次相比,如问题示例和 @ajcr)。 以下生成器只是逐行执行此操作:
def sc(x):
p = X.shape[1]
for i in range(p):
hold = np.array(x[:,i])
np.random.shuffle(x[:,i])
yield x
x[:,i] = hold
for i in sc(X):
print i
这给了:
[[ 2 5 11 15 20] # #0 column shuffled
[ 3 6 10 16 21]
[ 0 7 14 17 22]
[ 4 8 13 18 23]
[ 1 9 12 19 24]]
[[ 0 5 11 15 20] # #1 column shuffled
[ 1 8 10 16 21]
[ 2 9 14 17 22]
[ 3 7 13 18 23]
[ 4 6 12 19 24]]
# etc
另一方面,如果整个数组需要为每个列移次创建一个新副本,那就是时间的去向,
这是完全避免循环并构建所需数组的一种方法:
给定一个包含
n
列的数组X
,构造一个包含X
n
副本的数组Y
。创建一个掩码以从数组
Y
的第 i 个X
副本中选择第 i 列。
使用 掩码 on
Y
将X
的列随机副本重新分配给Y
的相关索引
在NumPy中,它看起来像这样:
>>> X = np.arange(9).reshape(3, 3)
>>> X
array([[0, 1, 2], # an example array
[3, 4, 5],
[6, 7, 8]])
>>> Y = X * np.ones((3, 3, 3))
>>> mask = zeros_like(Y)
>>> mask[[0,1,2],:,[0,1,2]] = 1
>>> mask = mask.astype(bool)
>>> Y[mask] = np.random.permutation(X).ravel('F')
>>> Y
array([[[ 6., 1., 2.], # first column shuffled
[ 0., 4., 5.],
[ 3., 7., 8.]],
[[ 0., 7., 2.], # second column shuffled
[ 3., 1., 5.],
[ 6., 4., 8.]],
[[ 0., 1., 8.], # third column shuffled
[ 3., 4., 2.],
[ 6., 7., 5.]]])