Python 从int'的ndarray创建字符串ndarray;旗帜';使用字符串意义列表

Python 从int'的ndarray创建字符串ndarray;旗帜';使用字符串意义列表,python,arrays,list,numpy,mapping,Python,Arrays,List,Numpy,Mapping,我试图从整数“标志”的ndarray开始: array([[1, 3, 2], [2, 0, 3], [3, 2, 0], [2, 0, 1]]) 到字符串的ndarray: array([['Banana', 'Celery', 'Carrot'], ['Carrot', 'Apple', 'Celery'], ['Celery', 'Carrot', 'Apple'], ['Carrot', 'Apple'

我试图从整数“标志”的
ndarray
开始:

array([[1, 3, 2],
       [2, 0, 3],
       [3, 2, 0],
       [2, 0, 1]])
到字符串的
ndarray

array([['Banana', 'Celery', 'Carrot'],
       ['Carrot', 'Apple', 'Celery'],
       ['Celery', 'Carrot', 'Apple'],
       ['Carrot', 'Apple', 'Banana']],
      dtype='|S6')
使用字符串列表作为“标志”到“含义”的映射:

meanings = ['Apple', 'Banana', 'Carrot', 'Celery']
我得出以下结论:

>>> import numpy as np
>>> meanings = ['Apple', 'Banana', 'Carrot', 'Celery']
>>> flags = np.array([[1,3,2],[2,0,3],[3,2,0],[2,0,1]])
>>> flags
array([[1, 3, 2],
       [2, 0, 3],
       [3, 2, 0],
       [2, 0, 1]])
>>> mapped = np.array([meanings[f] for f in flags.flatten()]).reshape(flags.shape)
>>> mapped
array([['Banana', 'Celery', 'Carrot'],
       ['Carrot', 'Apple', 'Celery'],
       ['Celery', 'Carrot', 'Apple'],
       ['Carrot', 'Apple', 'Banana']],
      dtype='|S6')
这是可行的,但我担心在处理大型
阵列时相关行的效率(列出comp、
展平、
重塑
):

np.array([meanings[f] for f in flags.flatten()]).reshape(flags.shape)

有没有更好/更有效的方法来执行这样的映射?

我认为
np.vectorize
是一种可行的方法,它也非常清晰且易于遵循。我还没有测试以下内容,但它应该可以工作

vfunc = np.vectorize(lambda x : meanings[x])

mapped = vfunc(flags)
花式索引是一种numpythonic方法:

mapped = meanings[flags]
或通常更快的等效物:

mapped = np.take(meanings, flags)

谢谢,这就像一个符咒——尽管你有一个输入错误:
mapped=vfunc(flags)
np.vectorize
是一个伪装的Python循环,而且你正在对每个数组项进行Python调用。它允许代码看起来更干净,但它给人一种错误的印象,即您将获得numpy性能,而事实并非如此。很长一段时间以来,我一直认为
np.vectorize
是用Cython编写和编译的,这使它在性能上具有优势,但Jamie是对的。谢谢@Jamie。不过需要注意的是,只有使用
np.take
的第二种解决方案可以与
ndims>1
一起使用。对于我的示例,第一个解决方案的结果是:
TypeError:只有带有一个元素的整数数组才能转换为索引,这是因为
means
是一个列表。如果您将其转换为一个ndarray(即
meansions=np.array(meansions)
),那么这两种方法将同样有效。