Convert a numpy array to an array of numpy arrays

前端 未结 2 1024
醉酒成梦
醉酒成梦 2021-01-17 03:19

How can I convert numpy array a to numpy array b in a (num)pythonic way. Solution should ideally work for arbitrary dimensions and array lengths.

2条回答
  •  有刺的猬
    2021-01-17 04:03

    For a start:

    In [638]: a=np.arange(12).reshape(2,3,2)
    In [639]: b=np.empty((2,3),dtype=object)
    In [640]: for index in np.ndindex(b.shape):
        b[index]=a[index]
       .....:     
    In [641]: b
    Out[641]: 
    array([[array([0, 1]), array([2, 3]), array([4, 5])],
           [array([6, 7]), array([8, 9]), array([10, 11])]], dtype=object)
    

    It's not ideal since it uses iteration. But I wonder whether it is even possible to access the elements of b in any other way. By using dtype=object you break the basic vectorization that numpy is known for. b is essentially a list with numpy multiarray shape overlay. dtype=object puts an impenetrable wall around those size 2 arrays.

    For example, a[:,:,0] gives me all the even numbers, in a (2,3) array. I can't get those numbers from b with just indexing. I have to use iteration:

    [b[index][0] for index in np.ndindex(b.shape)]
    # [0, 2, 4, 6, 8, 10]
    

    np.array tries to make the highest dimension array that it can, given the regularity of the data. To fool it into making an array of objects, we have to give an irregular list of lists or objects. For example we could:

    mylist = list(a.reshape(-1,2)) # list of arrays
    mylist.append([]) # make the list irregular
    b = np.array(mylist)  # array of objects
    b = b[:-1].reshape(2,3)  # cleanup
    

    The last solution suggests that my first one can be cleaned up a bit:

    b = np.empty((6,),dtype=object)
    b[:] = list(a.reshape(-1,2))
    b = b.reshape(2,3)
    

    I suspect that under the covers, the list() call does an iteration like

    [x for x in a.reshape(-1,2)]
    

    So time wise it might not be much different from the ndindex time.


    One thing that I wasn't expecting about b is that I can do math on it, with nearly the same generality as on a:

    b-10
    b += 10
    b *= 2
    

    An alternative to an object dtype would be a structured dtype, e.g.

    In [785]: b1=np.zeros((2,3),dtype=[('f0',int,(2,))])
    
    In [786]: b1['f0'][:]=a
    
    In [787]: b1
    Out[787]: 
    array([[([0, 1],), ([2, 3],), ([4, 5],)],
           [([6, 7],), ([8, 9],), ([10, 11],)]], 
          dtype=[('f0', '

    And b and b1 can be added: b+b1 (producing an object dtype). Curiouser and curiouser!

提交回复
热议问题