4

Say I have an array of the shape:

import numpy as np
a = np.zeros(shape=(3, 4, 2))

which looks like:

print a

[[[ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]]

 [[ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]]

 [[ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]
  [ 0.  0.]]]

How do I create an empty list with the same shape, where every 0. element is replaced by an empty sub-list?

In the specific case shown above, it would look like:

[[[[], []]
  [[], []]
  [[], []]
  [[], []]],
 [[[], []]
  [[], []]
  [[], []]
  [[], []]],
 [[[], []]
  [[], []]
  [[], []]
  [[], []]]]

but I need a way that works in general for arrays of any shape. Is there a built in function to do this?

2
  • When you write 'list' and sublist, do you mean Python lists, or numpy arrays? What do you intend to do with these empty sublists? Commented Mar 27, 2015 at 5:48
  • @hpaulj I mean Python list. In this question you can see what I need to do with these lists: stackoverflow.com/q/29300646/1391441 Commented Mar 27, 2015 at 12:29

3 Answers 3

6

np.empty(shape=(3, 4, 2, 0)) might be what you are looking for. Or more generally, np.empty(shape=your_shape+(0,)) where your_shape is a tuple like (3, 4, 2).

Now to get the desired list of lists, you can call the tolist method:

np.empty(shape=your_shape+(0,)).tolist()

Otherwhise, you could do a wrapper function that returns nested list comprehensions:

a = [[[[] for j in range(2)] for i in range(4)] for k in range(3)]

and if you want a numpy array:

a = np.array(a)

Such a function could be:

import copy
def empty(shape):
    if len(shape) == 1:
        return [[] for i in range(shape[0])]
    items = shape[0]
    newshape = shape[1:]
    sublist = empty(newshape)
    return [copy.deepcopy(sublist) for i in range(items)]

and you would call it like this:

a = empty([3,4,2])
Sign up to request clarification or add additional context in comments.

9 Comments

I didn't downvote but I'll venture the reason: I'm looking for a general solution that works on arrays of any shape. Your answer is applicable only to the example array used in the question.
@Gabriel let me know if this is a better answer.
Now to get the desired list of lists, just call the tolist method: np.empty(shape=a.shape+(0,)).tolist()
@JulienSpronck the first lines in your answer do not work, they return an empty list always. The function seem to have some issues. First of all, what is the call to empty(newshape)? This is not defined anywhere.
It's just a refinement of this answer. Maybe @JulienSpronck can edit it to include the use of tolist().
|
1
>>> a = np.zeros(shape=(3, 4, 2))
>>> r = np.empty((a.shape) + (0, ), dtype=object)
>>> r.fill([])
>>> r.tolist()
[[[[], []], [[], []], [[], []], [[], []]], [[[], []], [[], []], [[], []], [[], []]], [[[], []], [[], []], [[], []], [[], []]]]

3 Comments

This seems to have two problems. First, the extra dimension should be (1,). Second, r.fill([]) fills every cell with the same list.
This works for me (although the call to r.fill([]) is not necessary). The dtype of r irrelevant.
Works for me too, not sure what I was doing before to get an empty list.
1

If the goal is a multi dimensional array, where the individual items are Python lists, we need to be careful not to generate an array with a 0 dimension, or just a deeply nested list of lists.

One problem is that numpy readily transforms a list, empty or not, into an array. And by default it tries to create as high a dimensional array as possible. Thus for example

In [58]: np.array([[],[]])
Out[58]: array([], shape=(2, 0), dtype=float64)

There isn't a list dtype; the closest is object. And the surest way of generating object arrays is to initialize them as empty, and then fill the values:

In [54]: A = np.empty((3,4,2),dtype=object)

In [55]: A[0,0,0]=[] 

In [56]: A[:]=A[0,0,[0]]

In [57]: A
Out[57]: 
array([[[[], []],
        [[], []],
        [[], []],
        [[], []]],

       [[[], []],
        [[], []],
        [[], []],
        [[], []]],

       [[[], []],
        [[], []],
        [[], []],
        [[], []]]], dtype=object)

A[:]=[] does not work, because it treats the [] as a (0,) array:

ValueError: could not broadcast input array from shape (0) into shape (3,4,2)

The use of [0,0,0]and [0,0,[0]] assumes 3d, but that can be generalized to nd with a bit more work. This is just proof of concept.

But your other question about iterating through such an array made me wonder whether accessing such an array compares with accessing a simple list of lists. But maybe that discussion belongs in the other question.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.