我有以下数组和字典。
>>> data = ['a', 'b', 'a', 'a']
>>> mapping = {'a': 9, 'b': 0}
我想根据此输入字典应用将np.array(['a', 'b', 'a', 'a']
转换为np.array([9, 0, 9, 9])
的函数。但是我希望这个操作能够被矢量化。如果不使用for loop
,我该如何实现这种转换?
请注意,np.apply_along_axis和np.apply_over_axis都不起作用,因为它们要求输入数组为2-D。
编辑:请注意,我正在使用的实际数据集非常大,这里只是一个简单的例子。
答案 0 :(得分:3)
以下是一些想法。
首先,定义一些样本数据:
In [36]: data = np.array(['a', 'b', 'a', 'a', 'c', 'b'])
In [37]: mapping = {'a': 9, 'b': 0, 'c': 5}
您可以使用numpy.unique
获取data
中的唯一元素,以及(更重要的是)将这些唯一值映射回输入数组的数组:
In [38]: keys, inv = np.unique(data, return_inverse=True)
此时,keys[inv]
会重新创建data
。但我们想要创建映射数组,因此我们将在mapping
中创建值的数组,其顺序与np.unique
返回的键相同:
In [39]: vals = np.array([mapping[key] for key in keys])
现在我们可以使用vals
索引inv
以获得所需的结果:
In [40]: result = vals[inv]
In [41]: result
Out[41]: array([9, 0, 9, 9, 5, 0])
另一种非常简单的方法是简单地循环遍历mapping
中的键,并将值的矢量化赋值转换为新数组:
In [42]: result = np.empty(data.size, dtype=int)
In [43]: for key, val in mapping.items():
....: result[data == key] = val
....:
In [44]: result
Out[44]: array([9, 0, 9, 9, 5, 0])
如果不了解data
的实际尺寸和mapping
中的键数,则很难说哪种方法更有效。
这是您可能不想使用的方法,因为由表达式data.reshape(-1, 1) == keys
形成的2-d中间数组将具有形状(len(data), len(mapping))
:
In [63]: keys = np.array(mapping.keys())
In [64]: vals = np.array(mapping.values())
In [65]: result = vals[(data.reshape(-1, 1) == keys).nonzero()[1]]
In [66]: result
Out[66]: array([9, 0, 9, 9, 5, 0])
答案 1 :(得分:1)
如何简单地拨打map
?
>>> data = ['a', 'b', 'a', 'a']
>>> mapping = {'a': 9, 'b': 0}
>>> map(lambda x: mapping[x], data)
[9, 0, 9, 9]
这不会使用numpy,如果你的数组很大,也不会非常快,但它很简单,在你遇到性能问题之前可能不会担心。