【发布时间】:2020-06-03 21:49:12
【问题描述】:
给定以下数组:
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
[[1 2 3]
[4 5 6]
[7 8 9]]
如何将某些值替换为其他值?
bad_vals = [4, 2, 6]
update_vals = [11, 1, 8]
我目前使用:
for idx, v in enumerate(bad_vals):
a[a==v] = update_vals[idx]
这给出了:
[[ 1 1 3]
[11 5 8]
[ 7 8 9]]
但是替换具有许多值的大型数组相当慢。有什么好的选择吗?
输入数组可以更改为任何值(list/tuples 的list),如果这可能是访问某些快速黑魔法所必需的。
编辑:
基于@Divakar 和@charlysotelo 的出色回答,我使用benchit 包对我的真实用例日期进行了快速比较。我的输入数据数组的 a 或多或少的比率为 100:1 (rows:columns),其中替换值数组的长度按 3 x rows 大小的顺序排列。
功能:
# current approach
def enumerate_values(a, bad_vals, update_vals):
for idx, v in enumerate(bad_vals):
a[a==v] = update_vals[idx]
return a
# provided solution @Divakar
def map_values(a, bad_vals, update_vals):
N = max(a.max(), max(bad_vals))+1
mapar = np.empty(N, dtype=int)
mapar[a] = a
mapar[bad_vals] = update_vals
out = mapar[a]
return out
# provided solution @charlysotelo
def vectorize_values(a, bad_vals, update_vals):
bad_to_good_map = {}
for idx, bad_val in enumerate(bad_vals):
bad_to_good_map[bad_val] = update_vals[idx]
f = np.vectorize(lambda x: (bad_to_good_map[x] if x in bad_to_good_map else x))
a = f(a)
return a
# define benchit input functions
import benchit
funcs = [enumerate_values, map_values, vectorize_values]
# define benchit input variables to bench against
in_ = {
n: (
np.random.randint(0,n*10,(n,int(n * 0.01))), # array
np.random.choice(n*10, n*3,replace=False), # bad_vals
np.random.choice(n*10, n*3) # update_vals
)
for n in [300, 1000, 3000, 10000, 30000]
}
# do the bench
# btw: timing of bad approaches (my own function here) take time
t = benchit.timings(funcs, in_, multivar=True, input_name='Len')
t.plot(logx=True, grid=False)
【问题讨论】:
-
值(正)是整数吗?我们可以因此制作一个类似
[0,1,1,3,11,5,8]的列表(从而定义映射) -
您可以使用来自 Fast replacement of values in a numpy array 的答案,方法是根据 bad_vals 和 update_vals 制作字典。
-
@WillemVanOnsem 是的,所有值都是正整数
-
@Divakar,是的,会给!只好睡一会了。。