簡體   English   中英

NumPy列表理解語法

[英]NumPy List Comprehension Syntax

我希望能夠使用列表推導語法輕松地使用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

這樣做的簡單方法是什么,避免使用range(len(X)

首先,您不應該使用NumPy數組作為列表列表。

其次,讓我們忘掉NumPy; 你的listcomp首先沒有任何意義,即使對於列表列表也是如此。

在內部理解中, for i in X將迭代for i in X中的行。這些行不是數字,它們是列表(或者,在NumPy中,1D數組),因此X[i]沒有任何意義。 你可能想要i[j]

在外在理解中, for j in X[i]中的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])

...擴展到:

tmp = []
for j in X[i]:
    tmp2 = []
    for i in X:
        tmp2.append(X[i,j])
    tmp.append(tmp2)

......應該明白這里有什么問題。


我想你想要的是:

[[cell for cell in row] for row in X]

再次,把它放回明確for聲明:

tmp = []
for row in X;
    tmp2 = []
    for cell in row:
        tmp2.append(cell)
    tmp.append(tmp2)

那顯然是對的。

或者,如果你真的想使用索引(但你沒有):

[[X[i][j] for j in range(len(X[i]))] for i in range(len(X))]

所以,回到NumPy。 在NumPy術語中,最后一個版本是:

[[X[i,j] for j in range(X.shape[1])] for i in range(X.shape[0])]

...如果你想進入列主要順序而不是行主要,你可以(與列表列表不同):

[[X[i,j] for i in range(X.shape[0])] for j in range(X.shape[1])]

......但這當然會轉移陣列,這不是你想要做的。

不能做的一件事是在同一個表達式中混合列主要和行主要順序,因為你最終會廢話。


當然,制作數組副本的正確方法是使用copy方法:

X.copy()

正如轉置數組的正確方法是:

X.T

簡單的方法是不要這樣做。 改為使用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]])

然后使用列表推導的以下代碼:

C = numpy.array([[A[i, j] * B[i, j] for j in xrange(A.shape[1])]
                 for i in xrange(A.shape[0])])

可以更容易寫成

C = A * B

它也會運行得更快。 一般來說,如果你不使用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)]

因此,您的示例代碼將成為

numpy.array([[elem for elem in x_row] for x_row in X])

另一個選擇(雖然不一定是高性能)是將你的問題重新考慮為地圖而不是理解並編寫一個ufunc:

http://docs.scipy.org/doc/numpy/reference/ufuncs.html

您可以調用functional-lite例程,例如:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.apply_over_axes.html http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html

等等。

你的意思是關注?

>>> [[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]]

使用numpy.ndarray.copy

>>> 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]])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM