Python 重新分配numpy.array()

Python 重新分配numpy.array(),python,arrays,numpy,numpy-ndarray,Python,Arrays,Numpy,Numpy Ndarray,在下面的代码中,我可以轻松地将数组['a','b','a','c','b','b','c','a']简化为二进制数组[01101110],从而'a'->0和'b','c'->1。如何将其转换为三元数组,以便'a'->0,'b'->1,'c'->2,而不使用for和if else?谢谢 import numpy as np x = np.array(['a', 'b', 'a', 'c', 'b', 'b', 'c', 'a']) y = np.where(x=='a', 0, 1) print(

在下面的代码中,我可以轻松地将数组
['a','b','a','c','b','b','c','a']
简化为二进制数组
[01101110]
,从而
'a'->0
'b','c'->1
。如何将其转换为三元数组,以便
'a'->0
'b'->1
'c'->2
,而不使用
for
if else
?谢谢

import numpy as np
x = np.array(['a', 'b', 'a', 'c', 'b', 'b', 'c', 'a'])
y = np.where(x=='a', 0, 1)
print(y)
通过这样做:

np.where(x == 'a', 0, (np.where(x == 'b', 1, 2)))

请注意,这会将所有既不是“a”也不是“b”的字符更改为2。我假设您只有一个包含a、b和c的数组。

更具可扩展性的版本正在使用转换字典:

my_dict = {'a':0, 'b':1, 'c':2}
x = np.vectorize(my_dict.get)(x)
输出:

[0 1 0 2 1 1 2 0]
另一种方法是:

np.select([x==i for i in ['a','b','c']], np.arange(3))
对于小字典@ypno的答案会更快。对于较大的词典,请使用此答案


时间比较

lst = ['a','b','c']
my_dict = {k: v for v, k in enumerate(lst)}

#@Ehsan's solution1
def m1(x):
  return np.vectorize(my_dict.get)(x)

#@ypno's solution
def m2(x):
  return np.where(x == 'a', 0, (np.where(x == 'b', 1, 2)))

#@SteBog's solution
def m3(x):
  y = np.where(x=='a', 0, x)
  y = np.where(x=='b', 1, y)
  y = np.where(x=='c', 2, y)
  return y.astype(np.integer)

#@Ehsan's solution 2 (also suggested by user3483203 in comments)
def m4(x):
   return np.select([x==i for i in lst], np.arange(len(lst)))

#@juanpa.arrivillaga's solution suggested in comments
def m5(x):
  return np.array([my_dict[i] for i in x.tolist()])

in_ = [np.random.choice(lst, size = n) for n in [10,100,1000,10000,100000]]
lst = ['a','b','c','d','e','f','g','h']
三元字母表

lst = ['a','b','c']
my_dict = {k: v for v, k in enumerate(lst)}

#@Ehsan's solution1
def m1(x):
  return np.vectorize(my_dict.get)(x)

#@ypno's solution
def m2(x):
  return np.where(x == 'a', 0, (np.where(x == 'b', 1, 2)))

#@SteBog's solution
def m3(x):
  y = np.where(x=='a', 0, x)
  y = np.where(x=='b', 1, y)
  y = np.where(x=='c', 2, y)
  return y.astype(np.integer)

#@Ehsan's solution 2 (also suggested by user3483203 in comments)
def m4(x):
   return np.select([x==i for i in lst], np.arange(len(lst)))

#@juanpa.arrivillaga's solution suggested in comments
def m5(x):
  return np.array([my_dict[i] for i in x.tolist()])

in_ = [np.random.choice(lst, size = n) for n in [10,100,1000,10000,100000]]
lst = ['a','b','c','d','e','f','g','h']

对8个字母的字母表进行相同的分析

lst = ['a','b','c']
my_dict = {k: v for v, k in enumerate(lst)}

#@Ehsan's solution1
def m1(x):
  return np.vectorize(my_dict.get)(x)

#@ypno's solution
def m2(x):
  return np.where(x == 'a', 0, (np.where(x == 'b', 1, 2)))

#@SteBog's solution
def m3(x):
  y = np.where(x=='a', 0, x)
  y = np.where(x=='b', 1, y)
  y = np.where(x=='c', 2, y)
  return y.astype(np.integer)

#@Ehsan's solution 2 (also suggested by user3483203 in comments)
def m4(x):
   return np.select([x==i for i in lst], np.arange(len(lst)))

#@juanpa.arrivillaga's solution suggested in comments
def m5(x):
  return np.array([my_dict[i] for i in x.tolist()])

in_ = [np.random.choice(lst, size = n) for n in [10,100,1000,10000,100000]]
lst = ['a','b','c','d','e','f','g','h']

这将使数组的数据类型保持为字符串。因此,我认为您的输出将是数字字符串而不是整数。在末尾使用
y.astype(np.integer)
进行转换。提供的答案被标记为低质量帖子供审查。以下是一些指导原则。这一答案可以从解释中获益。仅代码答案不被视为“好”答案。从Review中。您应该使用
np。选择
可获得多个二进制结果。为什么要使用
np.vectorize
?这确实应该避免。几乎可以肯定,
np.array([my_dict[x]for x in array.tolist()])
会更快。@juanpa.arrivillaga感谢您的建议。请您提供更多信息,说明为什么确实应该避免这种情况。几乎可以肯定?我不知道实现的细节,但是如果您认为它在Numpy中是一个糟糕的实现,也许您可以向Numpy开发人员提出它。然而,一个个人的答案是可读性,这是主观的。另一个原因是
np.vectorize
对于较大的数组来说似乎比列表理解更快。为了更好地判断,我将添加时间比较。谢谢。直接从文档中可以看出:“提供矢量化函数主要是为了方便,而不是为了性能。实现基本上是一个for循环。”@juanpa.arrivillaga有趣。谢谢你的回复。请检查我更新的时间分析。对于较大的阵列,矢量化似乎稍微快一点。除非我遗漏了什么,否则向量化和简单循环似乎存在某种优化差异。很可能是转换为列表的开销。如果我真的这样做了,我就不会首先使用numpy.ndarray。在不使用
.tolist()的情况下尝试,然后在常规列表中尝试,我打赌您会看到,列表理解速度更快。