我希望能够使用列表推导语法轻松地使用NumPy数组.
例如,我想像下面明显错误的代码,只是重现相同的数组.
>>> X = np.random.randn(8,4)
>>> [[X[i,j] for i in X] for j in X[i]]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: arrays used as indices must be of integer (or boolean) type
Run Code Online (Sandbox Code Playgroud)
有什么简单的方法可以避免使用range(len(X)?
aba*_*ert 24
首先,您不应该将NumPy数组用作列表列表.
其次,让我们忘掉NumPy; 你的listcomp首先没有任何意义,即使对于列表列表也是如此.
在内部理解中,for i in X将迭代X中的行.这些行不是数字,它们是列表(或者,在NumPy,1D数组中),所以X[i]没有任何意义.你可能想要i[j].
在外在理解中,for j in X[i]有同样的问题,但是有一个更大的问题:没有i价值.你有一个理解循环每i 里面这个理解.
如果您对理解感到困惑,请将其写为明确的for语句,如List Comprehensions的教程部分所述:
tmp = []
for j in X[i]:
tmp.append([X[i,j] for i in X])
Run Code Online (Sandbox Code Playgroud)
...扩展到:
tmp = []
for j in X[i]:
tmp2 = []
for i in X:
tmp2.append(X[i,j])
tmp.append(tmp2)
Run Code Online (Sandbox Code Playgroud)
......应该明白这里有什么问题.
我想你想要的是:
[[cell for cell in row] for row in X]
Run Code Online (Sandbox Code Playgroud)
再次,将其转回显式for语句:
tmp = []
for row in X;
tmp2 = []
for cell in row:
tmp2.append(cell)
tmp.append(tmp2)
Run Code Online (Sandbox Code Playgroud)
那显然是对的.
或者,如果你真的想使用索引(但你没有):
[[X[i][j] for j in range(len(X[i]))] for i in range(len(X))]
Run Code Online (Sandbox Code Playgroud)
所以,回到NumPy.在NumPy术语中,最后一个版本是:
[[X[i,j] for j in range(X.shape[1])] for i in range(X.shape[0])]
Run Code Online (Sandbox Code Playgroud)
...如果你想进入列主要顺序而不是行主要,你可以(与列表列表不同):
[[X[i,j] for i in range(X.shape[0])] for j in range(X.shape[1])]
Run Code Online (Sandbox Code Playgroud)
......但这当然会转移阵列,这不是你想要做的.
你不能做的一件事是在同一个表达式中混合列主要和行主要顺序,因为你最终会废话.
当然,制作数组副本的正确方法是使用以下copy方法:
X.copy()
Run Code Online (Sandbox Code Playgroud)
正如转置数组的正确方法是:
X.T
Run Code Online (Sandbox Code Playgroud)
use*_*ica 11
简单的方法是不要这样做.改为使用numpy的隐式向量化.例如,如果您有数组A和B,如下所示:
A = numpy.array([[1, 3, 5],
[2, 4, 6],
[9, 8, 7]])
B = numpy.array([[5, 3, 5],
[3, 5, 3],
[5, 3, 5]])
Run Code Online (Sandbox Code Playgroud)
然后使用列表推导的以下代码:
C = numpy.array([[A[i, j] * B[i, j] for j in xrange(A.shape[1])]
for i in xrange(A.shape[0])])
Run Code Online (Sandbox Code Playgroud)
可以更容易写成
C = A * B
Run Code Online (Sandbox Code Playgroud)
它也会运行得更快.一般来说,如果你不使用numpy列表推导,你会产生更快,更清晰的代码.
如果您真的想使用列表推导,则应用标准的Python列表 - 理解 - 编写技术.迭代元素,而不是索引:
C = numpy.array([[a*b for a, b in zip(a_row, b_row)]
for a_row, b_row in zip(A, B)]
Run Code Online (Sandbox Code Playgroud)
因此,您的示例代码将成为
numpy.array([[elem for elem in x_row] for x_row in X])
Run Code Online (Sandbox Code Playgroud)
你的意思是跟随吗?
>>> [[X[i,j] for j in range(X.shape[1])] for i in range(X.shape[0])]
[[0.62757350000000001, -0.64486080999999995, -0.18372566000000001, 0.78470704000000002],
[1.78209799, -1.336448459999999 9, -1.3851422200000001, -0.49668994],
[-0.84148266000000005, 0.18864597999999999, -1.1135151299999999, -0.40225053999999 999],
[0.93852824999999995, 0.24652238000000001, 1.1481637499999999, -0.70346624999999996],
[0.83842508000000004, 1.0058 697599999999, -0.91267403000000002, 0.97991269000000003],
[-1.4265273000000001, -0.73465904999999998, 0.6684284999999999 8, -0.21551155],
[-1.1115614599999999, -1.0035033200000001, -0.11558254, -0.4339924],
[1.8771354, -1.0189299199999999, - 0.84754008000000003, -0.35387946999999997]]
Run Code Online (Sandbox Code Playgroud)
>>> X.copy()
array([[ 0.6275735 , -0.64486081, -0.18372566, 0.78470704],
[ 1.78209799, -1.33644846, -1.38514222, -0.49668994],
[-0.84148266, 0.18864598, -1.11351513, -0.40225054],
[ 0.93852825, 0.24652238, 1.14816375, -0.70346625],
[ 0.83842508, 1.00586976, -0.91267403, 0.97991269],
[-1.4265273 , -0.73465905, 0.6684285 , -0.21551155],
[-1.11156146, -1.00350332, -0.11558254, -0.4339924 ],
[ 1.8771354 , -1.01892992, -0.84754008, -0.35387947]])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
47222 次 |
| 最近记录: |