Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

numpy - transform a list of objects into an array without subclassing ndarray

For sake of simplicity I've defined a class that is not subclassed from ndarray (for many reasons I find it very complicated), but has an __array__() method that returns a nd.array of a given fixed shape. Let's call this class Foo.

In my script I also generate large lists of Foo instances, and I want to convert them into numpy arrays of arrays. I can easily do it using a map function:

numpy.array(map(lambda x: numpy.array(x), [foo_1, ..., foo_n]))

and it works fine. I was just wondering how I can get things ever more simpler and efficient, and get the following to work:

numpy.array([foo_1, ..., foo_n])

(actually it returns an "error return without exception set"...). It seems that providing an __array__ method is not sufficient to authorize array conversion of lists. Any idea?

like image 708
Ssbd78 Avatar asked Oct 21 '22 02:10

Ssbd78


1 Answers

From the numpy.array docs, the object you pass in must satisfy:

An array, any object exposing the array interface, an object whose __array__ method returns an array, or any (nested) sequence.

You're actually passing in a list of foo objects, so this list doesn't expose the array interface and doesn't have an array method. That leaves only whether it's a nested sequence. To be a nested sequence, your foo objects would likely need to be iterable. Are they? (emulating python's container types)

Not sure if this is any better, but you could probably do:

numpy.array([numpy.array(x) for x in [foo_1, ..., foo_n]])

Here is an example of Foo, as you've described. It outputs the ndarray you'd expect (no exceptions). Hopefully you can use it as an example:

import numpy as np

class Foo(object):
    def __init__(self):
        self.arr = np.array([[1, 2, 3], [4, 5, 6], [7,8,9]], np.int32)

    def __array__(self):
        return self.arr

    def __iter__(self):
        for elem in self.arr:
            yield elem

    def __len__(self):
        return len(self.arr)

    def __getitem__(self, key):
        return self.arr[key]

def main():
    foos = [Foo() for i in range(10)]
    print np.array(foos)


if __name__ == '__main__':
    main()
like image 137
Gerrat Avatar answered Oct 22 '22 17:10

Gerrat