最小的例子:
import numpy as np
def foo(arr):
negative = arr < 0
arr2 = arr 1
arr2[negative] *= -1
return arr2
a = np.array([1])
b = np.array(1)
print(foo(a)) # works, also works for any other nonzero dimensional array
print(foo(b)) # TypeError: 'numpy.int64' object does not support item assignment
有沒有一種優雅的方法來foo支持零維和非零維陣列?我更喜歡使用“pythonic”而不是基于arr2.ndim.
編輯:這個版本的 foo 似乎可以在沒有上述問題的情況下作業,盡管它修改了輸入。為什么這行得通,而不是上述?
def foo(arr):
negative = arr < 0
arr = 1
arr[negative] *= -1
return arr
uj5u.com熱心網友回復:
怎么用numpy.atleast1d?
def foo(arr):
negative = arr < 0
arr2 = np.atleast_1d(arr 1)
arr2[negative] *= -1
return arr2
foo(np.array(-5))
輸出:array([4])
uj5u.com熱心網友回復:
您可以將陣列的維度增加 1,執行操作,然后將維度減少 1:
def foo(arr):
arr = np.array([arr])
negative = arr < 0
arr2 = arr 1
arr2[negative] *= -1
return np.array(*arr2)
foo(np.array(-5))
輸出:
array(4)
uj5u.com熱心網友回復:
有一個問題 where arr2is not WRITEABLE, while arris :
for x in (np.array(1), np.array(1) 1):
print(x.dtype, x.ndim)
print(x.flags)
# int64 0
# C_CONTIGUOUS : True
# F_CONTIGUOUS : True
# OWNDATA : True
# WRITEABLE : True
# ALIGNED : True
# WRITEBACKIFCOPY : False
# UPDATEIFCOPY : False
# int64 0
# C_CONTIGUOUS : True
# F_CONTIGUOUS : True
# OWNDATA : True
# WRITEABLE : False
# ALIGNED : True
# WRITEBACKIFCOPY : False
# UPDATEIFCOPY : False
這導致賦值運算式失敗。
有許多解決方法:
- 預先復制輸入,以便您可以使用
=運算子來修改輸入的副本,該副本仍然是可寫的
def foo_cp(arr):
arr = arr.copy()
negative = arr < 0
arr = 1
arr[negative] *= -1
return arr
- 按照您最初的指示使用分支:
def foo_if(arr):
negative = arr < 0
arr2 = arr 1
if negative.ndim > 0:
arr2[negative] *= -1
elif arr < 0:
arr2 = -arr2
return arr2
- 使用等價的代數運算式
def foo_float(arr):
return np.sign(np.sign(arr) 0.5).astype(np.int8) * (arr 1)
對于整數,上面可以簡化為:
def foo_int(arr):
return np.abs(arr 1)
下面的一些測驗顯示了所有這些最終如何作業并為指定的用例產生正確的輸出:
funcs = foo_cp, foo_if, foo_float, foo_int, foo_atl1d, foo_updown
int_arrs = [np.arange(-20, 20), np.array([2]), np.array(2), np.array([-1]), np.array(-1), np.array(-2)]
float_arrs = [np.arange(-20, 20) / np.pi, np.array([1.2]), np.array(1.2), np.array([-0.5]), np.array(-0.5), np.array(1.2)]
int_base = [funcs[0](arr) for arr in int_arrs]
float_base = [funcs[0](arr) for arr in float_arrs]
for func in funcs:
int_res = [func(arr) for arr in int_arrs]
float_res = [func(arr) for arr in float_arrs]
is_good_int = all(np.allclose(x, y) for x, y in zip(int_base, int_res))
is_good_float = all(np.allclose(x, y) for x, y in zip(float_base, float_res))
print(f"{func.__name__:>12} {is_good_int!s:>5} {is_good_float!s:>5} ", end="")
%timeit -n 64 -r 4 [func(arr) for arr in int_arrs]; [func(arr) for arr in float_arrs]
# foo_cp True True 64 loops, best of 4: 74.6 μs per loop
# foo_if True True 64 loops, best of 4: 53.7 μs per loop
# foo_float True True 64 loops, best of 4: 85.8 μs per loop
# foo_int True False 64 loops, best of 4: 28.4 μs per loop
# foo_atl1d True True 64 loops, best of 4: 177 μs per loop
# foo_updown True True 64 loops, best of 4: 115 μs per loop
(我還包括foo_atl1d()來自@mozway 的回答和@Nin17foo_updown()的回答)。
請注意,雖然foo_cp()orfoo_float()可能更容易撰寫,但它們可能比foo_if(). 另一方面,foo_int()可能是最快的。foo_atl1d()并且foo_updown()似乎是最慢的(對于經過測驗的輸入)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/494382.html
標籤:Python 数组 麻木的 numpy-ndarray
上一篇:Python中的列標題格式
