4

I have a function that sometimes gives me a list of lists where the nested lists sometimes only have one item, such as this one:

a = [['1'], ['3'], ['w']]

And want to randomly select one item from that main list a. If I try to use np.random.choice on this list, I get a ValueError: a must be 1-dimensional.

But if the list were instead:

b = [['1'], ['3'], ['w', 'w']]

Then using np.random.choice works perfectly fine. Why is this? And how can I make it so that I can randomly select from both types of lists?

chunpoon
  • 950
  • 10
  • 17

2 Answers2

3

I think choice is first turning your list into an array.

In the second case, this array is a 1d array with dtype object:

In [125]: np.array([['1'], ['3'], ['w', 'w']])
Out[125]: array([['1'], ['3'], ['w', 'w']], dtype=object)
In [126]: _.shape
Out[126]: (3,)

In the second, it makes a 2d array of strings:

In [127]: np.array([['1'], ['3'], ['w']])
Out[127]: 
array([['1'],
       ['3'],
       ['w']], 
      dtype='<U1')
In [128]: _.shape
Out[128]: (3, 1)

This is an issue that comes up periodically. np.array tries to create as a high a dimensional array as the input allows.

Prevent numpy from creating a multidimensional array

Community
  • 1
  • 1
hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • No need to just "think" it; you can find the code in https://github.com/numpy/numpy/blob/master/numpy/random/mtrand/mtrand.pyx, where you'll find that the first thing `choice` does is `a = np.array(a, copy=False)`. – Warren Weckesser Aug 07 '16 at 19:03
  • Now I'm off to discard the answer I was editing. hpaulj is just too fast. :) – Warren Weckesser Aug 07 '16 at 19:04
0

To answer the "how to make it work" part you can use:

np.random.choice(np.squeeze(a))

Note that this will eliminate the square brackets for a, but not for b. But might still be useful.

Aguy
  • 7,851
  • 5
  • 31
  • 58