In Python 2 I could do the following:
import numpy as np f = lambda x: x**2 seq = map(f, xrange(5)) seq = np.array(seq) print seq # prints: [ 0 1 4 9 16]
In Python 3 it does not work anymore:
import numpy as np f = lambda x: x**2 seq = map(f, range(5)) seq = np.array(seq) print(seq) # prints: <map object at 0x10341e310>
How do I get the old behaviour (converting the map
results to numpy
array)?
Edit: As @jonrsharpe pointed out in his answer this could be fixed if I converted seq
to a list first:
seq = np.array(list(seq))
but I would prefer to avoid the extra call to list
.
Method 1: numpy.vectorize() function maps functions on data structures that contain a sequence of objects like NumPy arrays. The nested sequence of objects or NumPy arrays as inputs and returns a single NumPy array or a tuple of NumPy arrays.
Using numpy.asarray() , and true (by default) in the case of np. array() . This means that np. array() will make a copy of the object (by default) and convert that to an array, while np.
The array object in NumPy is called ndarray . We can create a NumPy ndarray object by using the array() function.
One more alternative, other than the valid solutions @jonrsharpe already pointed out is to use np.fromiter
:
>>> import numpy as np >>> f = lambda x: x**2 >>> seq = map(f, range(5)) >>> np.fromiter(seq, dtype=np.int) array([ 0, 1, 4, 9, 16])
Although you refer to it as seq
, the map
object in Python 3 is not a sequence (it's an iterator, see what's new in Python 3). numpy.array
needs a sequence so the len
can be determined and the appropriate amount of memory reserved; it won't consume an iterator. For example, the range
object, which does support most sequence operations, can be passed directly;
seq = np.array(range(5)) print(seq) # prints: [0 1 2 3 4]
To restore the previous behaviour, as you're aware, you can explicitly convert the map
object back to a sequence (e.g. list or tuple):
seq = np.array(list(seq)) # should probably change the name!
However, as the documentation puts it:
a quick fix is to wrap
map()
inlist()
, e.g.list(map(...))
, but a better fix is often to use a list comprehension (especially when the original code useslambda
)
So another option would be:
seq = [f(x) for x in range(5)]
or just:
seq = [x**2 for x in range(5)]
Alternatively, actually use numpy
from the start:
import numpy as np arr = np.arange(5) arr **= 2 print(arr) # prints [ 0 1 4 9 16] in 2.x and 3.x
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With