![](/img/trans.png)
[英]How can I get my function to return more than 1 result (with for-loops and dictionaries) in Python?
[英]How do I shift my thinking to 'vectorize my computation' more than using 'for-loops'?
這絕對是一個概念性問題,但是我想在SO上讓其他人就此主題提供專業意見。 最近,我的大部分編程工作都來自Numpy數組。 我一直在匹配兩個左右大小不同的數組中的項目。 大多數時候,我會去for-loop,甚至最糟糕的是嵌套的for-loop。 我最終嘗試避免使用for循環,因為我嘗試在Data Science中獲得更多經驗,因為for循環的執行速度較慢。
我非常了解Numpy和我可以研究的預定義cmd,但是對於那些經驗豐富的人, 當您遍歷某些內容時,您是否具有一般的思路?
類似於以下內容:
small_array = np.array(["a", "b"])
big_array = np.array(["a", "b", "c", "d"])
for i in range(len(small_array)):
for p in range(len(big_array)):
if small_array[i] == big_array[p]:
print "This item is matched: ", small_array[i]
我很清楚有一種方法可以用這種方法給貓咪剝皮,但是我對其他方法和思維方式很感興趣。
由於我從事數組語言(APL,MATLAB和numpy)已有數十年的經驗,因此我無法幫助您入門。 但是我懷疑我主要是根據模式,過去見過和使用過的東西工作。 我在互動環節中做了很多實驗。
舉個例子:
In [273]: small_array = np.array(["a", "b"])
...: big_array = np.array(["a", "b", "c", "d"])
...:
...: for i in range(len(small_array)):
...: for p in range(len(big_array)):
...: if small_array[i] == big_array[p]:
...: print( "This item is matched: ", small_array[i])
...:
This item is matched: a
This item is matched: b
通常,我運行迭代案例只是為了清楚地了解所需的內容。
In [274]: small_array
Out[274]:
array(['a', 'b'],
dtype='<U1')
In [275]: big_array
Out[275]:
array(['a', 'b', 'c', 'd'],
dtype='<U1')
我之前見過-遍歷兩個數組,並對成對的值進行處理。 這是一種outer
操作。 有多種工具,但我最喜歡的一種工具是使用numpy
廣播。 它將一個數組轉換為(n,1)數組,並將其與另一個(m,)數組一起使用
In [276]: small_array[:,None]
Out[276]:
array([['a'],
['b']],
dtype='<U1')
用(1,m)運算的(n,1)的結果是(n,m)數組:
In [277]: small_array[:,None]==big_array
Out[277]:
array([[ True, False, False, False],
[False, True, False, False]], dtype=bool)
現在,我可以在任一軸上進行any
或all
縮減:
In [278]: _.all(axis=0)
Out[278]: array([False, False, False, False], dtype=bool)
In [280]: __.all(axis=1)
Out[280]: array([False, False], dtype=bool)
我也可以使用np.where
將布爾值減少為索引。
糟糕,我應該使用any
In [284]: (small_array[:,None]==big_array).any(0)
Out[284]: array([ True, True, False, False], dtype=bool)
In [285]: (small_array[:,None]==big_array).any(1)
Out[285]: array([ True, True], dtype=bool)
玩過這個游戲后,我記得有一個in1d
做類似的事情
In [286]: np.in1d(big_array, small_array)
Out[286]: array([ True, True, False, False], dtype=bool)
但是,當我查看in1d
的代碼時(請參閱文檔中的[source]
鏈接),我看到,在某些情況下,它實際上是在小數組上進行迭代的:
In [288]: for x in small_array:
...: print(x==big_array)
...:
[ True False False False]
[False True False False]
將此與Out[277]
進行比較。 x==big_array
將標量與數組進行比較。 在numpy
,使用數組和標量執行==
, +
, *
等類似的操作很容易,並且應該成為第二自然。 下一步是對2個匹配形狀的數組進行相同的操作。 然后從那里開始播放可廣播的形狀。
在其他情況下,它使用np.unique
和np.argsort
。
通過相互廣播輸入,然后將值與某種歸約方式(任意,全部,和,均值等)進行組合來創建更高維數組的這種模式非常普遍。
我將以更具體的方式解釋您的問題:
如何使用索引變量退出?
如何開始編寫列表推導而不是普通循環”?
要退出使用索引變量,關鍵是要了解Python中的“ for”不是其他語言的“ for”。 應該將其稱為“每個”。
for x in small_array:
for y in big_array:
if x == y:
print "This item is matched: ", x
那好多了。
我也發現自己會用普通的循環編寫代碼(或者實際上是這樣做),然后開始懷疑列表理解是否會更清晰,更優雅。
列表理解實際上是創建列表的特定於領域的語言,因此第一步將是學習其基礎知識。 典型的陳述是:
l = [f(x) for x in list_expression if g(x)]
意思是“為list_expression中滿足條件g的所有x給我一個f(x)列表”
因此,您可以通過以下方式編寫它:
matched = [x for x in small_array if x in big_array]
等等 ,您正邁向Python風格!
如您所說,最好使用矢量化的東西來加快速度。 學習這是一條漫長的道路。 如果您還沒有使用矩陣乘法,則必須使用它。 一旦使用完,請嘗試將數據轉換為矩陣並查看可以執行的乘法。 通常,您無法執行此操作並擁有超矩陣(超過2D維度)。 那是numpy變得有用的地方。
Numpy提供了一些功能,例如np.where
,知道如何使用它們。 了解諸如small_array[small_array == 'a'] = 'z'
類的快捷方式。 嘗試將numpy函數與nativ python(地圖,過濾器...)結合使用。
要處理多維矩陣,不需要任何秘密,練習和使用紙張來了解您在做什么。 但是從4個維度開始,它變得非常棘手。
for循環不一定很慢。 由於matlab自身的錯誤,這是隨時間流逝的matlab廢話。 向量化是 “用於”循環的,但級別較低。 您需要掌握要處理哪種數據和體系結構以及對數據執行哪種功能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.