【发布时间】:2020-11-27 03:59:34
【问题描述】:
following up on another question
import numpy as np
repeat=int(1e5)
r_base = np.linspace(0,4,5)
a_base = 2
np.random.seed(0)
r_mat = r_base * np.random.uniform(0.9,1.1,(repeat,5))
a_array = a_base * np.random.uniform(0.9,1.1, repeat)
# original slow approach
def func_vetorized_level1(r_row, a):
if r_row.mean()>2:
result = np.where((r_row >= a), r_row - a, np.nan)
else:
result = np.where((r_row >= a), r_row + a, 0)
return result
# try to broadcast this func to every row of r_mat using list comprehension
def func_list_level2(r_mat, a_array):
res_mat = np.array([func_vetorized_level1(this_r_row, this_a)
for this_r_row, this_a in zip(r_mat, a_array)])
return res_mat
# faster with direct masking, but with unnecessary more calculation
def f_faster(r_mat,a_array):
a = a_array[:, None] # to column vector
row_mask = (r_mat.mean(axis=1) > 2)[:,None]
elem_mask = r_mat >= a
out = np.empty_like(r_mat)
out[row_mask & elem_mask] = (r_mat - a)[row_mask & elem_mask]
out[~row_mask & elem_mask] = (r_mat + a)[~row_mask & elem_mask]
out[row_mask & ~elem_mask] = np.nan
out[~row_mask & ~elem_mask] = 0
return out
# fastest with ufunc in numpy as suggested by @mad_physicist
def f_fastest(r_mat,a_array):
a = a_array[:, None] # to column vector
row_mask = (r_mat.mean(axis=1) > 2)[:,None]
elem_mask = r_mat >= a
out = np.empty_like(r_mat)
np.subtract(r_mat, a, out=out, where=row_mask & elem_mask)
np.add(r_mat, a, out=out, where=~row_mask & elem_mask)
out[row_mask & ~elem_mask] = np.nan
out[~row_mask & ~elem_mask] = 0
return out
我想问是否有可能有一个可以使用的用户定义函数,或者利用最快的方法?我考虑过使用索引,但发现它具有挑战性,因为使用[row_ind, co_ind] 的切片元素是所选元素的一维数组。我看到可以使用reshape 将切片矩阵放入矩阵中,但是有没有一种优雅的方法呢?理想情况下,这个r_mat + a 操作可以被用户定义的函数替换。
【问题讨论】:
-
简短的回答是否定的,你不能有一个完全任意的用户定义的函数而不循环。但是,您可以强制用户提供一个接受
where作为参数的函数。 -
等等,没关系。您之前已经回答了自己的问题。将立即发布。
-
np.frompyfunc确实创建了一个ufunc,它采用了out和where,但速度与内置的ufunc完全不同。
标签: python numpy conditional-statements vectorization