我有一個功能:
def aspect_good(angle: float, planet1_good: bool, planet2_good: bool):
"""
Decides if the angle represents a good aspect.
NOTE: returns None if the angle doesn't represent an aspect.
"""
if 112 <= angle <= 128 or 52 <= angle <= 68:
return True
elif 174 <= angle <= 186 or 84 <= angle <= 96:
return False
elif 0 <= angle <= 8 and planet1_good and planet2_good:
return True
elif 0 <= angle <= 6:
return False
else:
return None
我想對它進行矢量化,這樣我就可以傳入 numpy 陣列,而不是為每個引數傳遞一個值。簽名將如下所示:
def aspect_good(
angles: np.ndarray[float],
planet1_good: np.ndarray[bool],
planet2_good: np.ndarray[bool],
) -> np.array[bool | None]:
我不知道該怎么做,我可以轉換每個 if, elif 陳述句:
((112 <= angles) & (angles <= 128)) | ((52 <= angles) & (angles <= 68))
((174 <= angles) & (angles <= 186)) | ((84 <= angles) & (angles <= 96))
((0 <= angles) & (angles <= 8)) & planets1_good & planets2_good
((0 <= angles) & (angles <= 6))
# how to convert the 'else' statement?
但我現在不確定如何連接它們。有人可以幫忙嗎?我對numpy沒有很多經驗,也許它有一些有用的功能可以做到這一點。
更新
非常感謝大家,尤其是@Mad Physicist
.
所以,我可以使用這個:
def aspect_good(angles: np.typing.ArrayLike, planets1_good: np.typing.ArrayLike, planets2_good: np.typing.ArrayLike) -> np.typing.NDArray:
"""
Decides if the angle represents a good aspect.
"""
result = np.full_like(angle, -1, dtype=np.int8)
false_mask = np.abs(angle % 90) <= 6
result[false_mask] = 0
true_mask = np.abs(angle % 60) <= 8
result[true_mask] = 1
return result
這太棒了!向瘋狂的物理學家致敬,這個解決方案是如此美麗和簡單,甚至比我以前的解決方案還要簡單。祝您生活愉快,好先生!
uj5u.com熱心網友回復:
要在 numpy 中撰寫代碼,您需要通過幾種方式調整您的想法。
最大的是矢量化。您不能讓if
陳述句單獨處理每個元素并且仍然高效,因此您需要將邏輯轉換為更簡化的東西。
另一點是你不能有一個三值布林值。這意味著您要么必須重新定義條件以適應真偽二分法,要么使用不同的資料型別。我將展示后一種方法,其值為0
False、1
True 和-1
None 的整數。
每種情況都著眼于角度,而我只看到一個范圍碰撞。我會推薦以下方法:
- 制作一個用 None 值填充的輸出陣列 (-1)
- 找出要設定為 False 的值,然后執行此操作
- 找出要設定為 True 的值,然后執行此操作
angle <= 6
這里的順序很重要,因為當兩個行星都很好時,您希望 True 值取代 False 值。
def aspect_good(angle: np.typing.ArrayLike, planet1_good: np.typing.ArrayLike, planet2_good: np.typing.ArrayLike) -> np.typing.NDArray:
"""
Decides if the angle represents a good aspect.
NOTE: returns None if the angle doesn't represent an aspect.
"""
result = np.full_like(angle, -1, dtype=np.int8)
false_mask = ((174 <= angle) & (angle <= 186)) | ((84 <= angle) & (angle <= 96)) | ((0 <= angle) & (angle <= 6))
result[false_mask] = 0
true_mask = ((112 <= angle) & (angle <= 128)) | ((52 <= angle) & (angle <= 68)) | ((0 <= angle) & (angle <= 8) & planet1_good & planet2_good)
result[true_mask] = 1
return result
這些額外的括號很重要:與邏輯運算子不同,位運算子比比較運算子具有更緊密的系結。
此函式不關心您是否傳入多維陣列或planet*_good
. 重要的是三個輸入相互廣播。
您可以將范圍條件重鑄為距中點的距離:
false_mask = (np.abs(angle - 180) <= 6) | (np.abs(angle - 90) <= 6) | (np.abs(angle - 3) <= 3)
出于好奇,您的意思是使用以下簡化嗎?
false_mask = np.abs(angle % 90) <= 6
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/507402.html
上一篇:如何沿陣列維度映射克羅內克積?