Jim Hunziker
Jim Hunziker

Reputation: 15370

How can I fill a numpy array with empty builtin lists?

I'm filling a numpy grid with lists of unknown size because list.append is better to use than np.concatenate (perhaps I'm optimizing prematurely, though).

These don't work:

foo = np.full((3, 4), []) 
bar = np.full((3, 4), [], dtype=object) 

Numpy just assumes that my [] is a numpy array for populating the result and is the wrong shape.

It works for dicts:

foo = np.full((3, 4), {})

Is there some way to do this?

Edit: actually, I don't know how to do this even with numpy arrays. I want a 2x2 grid with variable length lists or arrays in each cell.

Edit 2: what I really want is something like scipy.stats.binned_statistic_2d but instead of a statistic in each bin, I want to keep the source data.

Upvotes: 0

Views: 356

Answers (1)

hpaulj
hpaulj

Reputation: 231335

full with a mutable object, even when it works has problems:

In [10]: A = np.full(3,{})                                                      
In [11]: A                                                                      
Out[11]: array([{}, {}, {}], dtype=object)
In [12]: A[0]['k']=2                                                            
In [13]: A                                                                      
Out[13]: array([{'k': 2}, {'k': 2}, {'k': 2}], dtype=object)

Like

In [14]: [{}]*3                                                                 
Out[14]: [{}, {}, {}]

it's putting the same object in each slot.

You could create an 'blank' object dtype array, and fill it from a list - taking care that each element is a 'fresh' list:

In [15]: A = np.empty((2,2),object)                                             
In [16]: A                                                                      
Out[16]: 
array([[None, None],
       [None, None]], dtype=object)
In [17]: A[:] = [[[] for _ in range(2)] for _ in range(2)]                      
In [18]: A                                                                      
Out[18]: 
array([[list([]), list([])],
       [list([]), list([])]], dtype=object)
In [19]: A[0,0].append(34)                                                      
In [20]: A                                                                      
Out[20]: 
array([[list([34]), list([])],
       [list([]), list([])]], dtype=object)

frompyfunc is a good tool for creating object dtype arrays, filled with all sorts of object classes:

In [23]: B = np.frompyfunc(lambda x:[],1,1)(np.zeros((2,2)))                    
In [24]: B                                                                      
Out[24]: 
array([[list([]), list([])],
       [list([]), list([])]], dtype=object)
In [25]: B[0,0].append(34)                                                      
In [26]: B                                                                      
Out[26]: 
array([[list([34]), list([])],
       [list([]), list([])]], dtype=object)

This too is creating a 'fresh' list for each element.

Upvotes: 2

Related Questions