简体   繁体   English

用ufunc映射numpy数组

[英]Map numpy array with ufunc

I'm trying to efficiently map a N * 1 numpy array of ints to a N * 3 numpy array of floats using a ufunc. 我正在尝试使用ufunc将N * 1 numpy的整数数组有效地映射到N * 3 numpy的浮点数组。

What I have so far: 到目前为止,我有:

map = {1: (0, 0, 0), 2: (0.5, 0.5, 0.5), 3: (1, 1, 1)}
ufunc = numpy.frompyfunc(lambda x: numpy.array(map[x], numpy.float32), 1, 1)

input = numpy.array([1, 2, 3], numpy.int32)

ufunc(input) gives a 3 * 3 array with dtype object. ufunc(input)给出一个3 * 3的dtype对象数组。 I'd like this array but with dtype float32. 我想要这个数组,但使用dtype float32。

You could use np.hstack : 您可以使用np.hstack

import numpy as np
mapping = {1: (0, 0, 0), 2: (0.5, 0.5, 0.5), 3: (1, 1, 1)}
ufunc = np.frompyfunc(lambda x: np.array(mapping[x], np.float32), 1, 1, dtype = np.float32)

data = np.array([1, 2, 3], np.int32)
result = np.hstack(ufunc(data))
print(result)
# [ 0.   0.   0.   0.5  0.5  0.5  1.   1.   1. ]
print(result.dtype)
# float32
print(result.shape)
# (9,)

You can use ndarray fancy index to get the same result, I think it should be faster than frompyfunc: 您可以使用ndarray花式索引来获得相同的结果,我认为它应该比frompyfunc更快:

map_array = np.array([[0,0,0],[0,0,0],[0.5,0.5,0.5],[1,1,1]], dtype=np.float32)
index = np.array([1,2,3,1])
map_array[index]

Or you can just use list comprehension: 或者,您可以只使用列表理解:

map = {1: (0, 0, 0), 2: (0.5, 0.5, 0.5), 3: (1, 1, 1)}
np.array([map[i] for i in [1,2,3,1]], dtype=np.float32)    

If your mapping is a numpy array, you can just use fancy indexing for this: 如果您的映射是一个numpy数组,则可以为此使用花式索引:

>>> valmap = numpy.array([(0, 0, 0), (0.5, 0.5, 0.5), (1, 1, 1)])
>>> input = numpy.array([1, 2, 3], numpy.int32)
>>> valmap[input-1]
array([[ 0. ,  0. ,  0. ],
       [ 0.5,  0.5,  0.5],
       [ 1. ,  1. ,  1. ]])

Unless I misread the doc, the output of np.frompyfunc on a scalar a object indeed: when using a ndarray as input, you'll get a ndarray with dtype=obj . 除非我误读了doc,否则确实将np.frompyfunc在标量上的输出是对象:当使用ndarray作为输入时,您将获得ndarray dtype=objndarray

A workaround is to use the np.vectorize function: 一种解决方法是使用np.vectorize函数:

F = np.vectorize(lambda x: mapper.get(x), 'fff')

Here, we force the dtype of F 's output to be 3 floats (hence the 'fff' ). 在这里,我们强制F的输出的dtype为3个浮点数(因此为'fff' )。

>>> mapper = {1: (0, 0, 0), 2: (0.5, 1.0, 0.5), 3: (1, 2, 1)}
>>> inp = [1, 2, 3]
>>> F(inp)
(array([ 0. ,  0.5,  1. ], dtype=float32), array([ 0.,  0.5,  1.], dtype=float32), array([ 0. ,  0.5,  1. ], dtype=float32))

OK, not quite what we want: it's a tuple of three float arrays (as we gave 'fff'), the first array being equivalent to [mapper[i][0] for i in inp] . 好吧,不是我们想要的:这是三个浮点数组的元组(正如我们给的'fff'),第一个数组等效于[mapper[i][0] for i in inp] So, with a bit of manipulation: 因此,通过一些操作:

>>> np.array(F(inp)).T
array([[ 0. ,  0. ,  0. ],
       [ 0.5,  0.5,  0.5],
       [ 1. ,  1. ,  1. ]], dtype=float32)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM